Example: ASCII to Unicode Conversion
Program 1-3, which used the CopyFile convenience function. File copying is familiar by now, so this example also converts a file to Unicode, assuming it is ASCII; there is no test. The program also includes some error reporting and an option to suppress replacement of an existing file, and it replaces the final call to CopyFile with a new function that performs the ASCII to Unicode file conversion.This program is concerned mostly with ensuring that the conversion can take place successfully. The operation is captured in a single function call at the end. This boilerplate, similar to that in the previous program, will be used again in the future but will not be repeated in the text.Notice the call to _taccess, which tests the file's existence. This is a generic version of the access function, which is in the UNIX library but is not part of the Standard C library. It is defined in <io.h>. More precisely, _taccess tests to seewhether the file is accessible according to the mode in the second parameter. A value of 0 tests for existence, 2 for write permission, 4 for read permission, and 6 for read-write permission (these values are not directly related to the Windows access values, such as GENERIC_READ). The alternative to test for the file's existence would be to open a handle with CreateFile and then close the handle after a validity test.
Program 2-4. atou: File Conversion with Error Reporting
Program 2-5 is the conversion function Asc2Un called by Program 2-4.
/* Chapter 2. atou -- ASCII to Unicode file copy. */
#include "EvryThng.h"
BOOL Asc2Un (LPCTSTR, LPCTSTR, BOOL);
int _tmain (int argc, LPTSTR argv [])
{
DWORD LocFileIn, LocFileOut;
BOOL DashI = FALSE;
TCHAR YNResp [3] = _T ("y");
/* Get the command line options and the index of the input file. */
LocFileIn = Options (argc, argv, _T ("i"), &DashI, NULL);
LocFileOut = LocFileIn + 1;
if (DashI) { /* Does output file exist? */
/* Generic version of access function to test existence. */
if (_taccess (argv [LocFileOut], 0) == 0) {
_tprintf (_T ("Overwrite existing file? [y/n]"));
_tscanf (_T ("%s"), &YNResp);
if (lstrcmp (CharLower (YNResp), YES) != 0)
ReportError (_T ("Will not overwrite"), 4, FALSE);
}
}
/* This function is modeled on CopyFile. */
Asc2Un (argv [LocFileIn], argv [LocFileOut], FALSE);
return 0;
}
Program 2-5. Asc2Un Function
#include "EvryThng.h"
#define BUF_SIZE 256
BOOL Asc2Un (LPCTSTR fIn, LPCTSTR fOut, BOOL bFailIfExists)
/* ASCII to Unicode file copy function.
Behavior is modeled after CopyFile. */
{
HANDLE hIn, hOut;
DWORD dwOut, nIn, nOut, iCopy;
CHAR aBuffer [BUF_SIZE];
WCHAR uBuffer [BUF_SIZE];
BOOL WriteOK = TRUE;
hIn = CreateFile (fIn, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
/* Determine CreateFile action if output file already exists. */
dwOut = bFailIfExists ? CREATE_NEW : CREATE_ALWAYS;
hOut = CreateFile (fOut, GENERIC_WRITE, 0, NULL,
dwOut, FILE_ATTRIBUTE_NORMAL, NULL);
while (ReadFile (hIn, aBuffer, BUF_SIZE, &nIn, NULL)
&& nIn > 0 && WriteOK) {
for (iCopy = 0; iCopy < nIn; iCopy++)
/* Convert each character. */
uBuffer [iCopy] = (WCHAR) aBuffer [iCopy];
WriteOK = WriteFile (hOut, uBuffer, 2 * nIn, &nOut, NULL);
}
CloseHandle (hIn);
CloseHandle (hOut);
return WriteOK;
}
Performance
Appendix C shows that the performance of the file conversion program can be improved by using such techniques as providing a larger buffer and by specifying FILE_FLAG_SEQUENTIAL_SCAN with CreateFile. Appendix C also contrasts performance on NTFS and distributed file systems.