5.2.2 Example: Reading, Writing, and Locking Files

The ReadFile function requires a file handle that is open for reading, or reading and writing; WriteFile requires a file handle that is open for writing, or writing and reading. ReadFile copies a specified number of bytes, up to the end of the file, to a specified buffer, and returns the actual number of bytes read in its fourth parameter. WriteFile copies a specified number of bytes, up to the end of the buffer, to a specified file, and returns the actual number of bytes written in its fourth parameter.

The SetFilePointer function moves the file pointer a specified number of bytes, relative to the beginning of the file, the end of the file, or the file pointer's current position. If you specify a positive number of bytes, SetFilePointer moves the file pointer toward the beginning of the file; a negative value moves the pointer toward the end of the file.

The following code fragment appends one file to the end of another file.

The application opens two files with CreateFile: ONE.TXT is opened for reading and TWO.TXT is opened for writing. Then, the application appends the contents of ONE.TXT to the end of TWO.TXT by reading and writing 4K blocks with ReadFile and WriteFile. Before writing to the second file, the application sets the second file's pointer to the end of the file by using SetFilePointer and locks the area to be written by using LockFile. This prevents another process from accessing the area while the write is in progress. After each write, UnlockFile unlocks the locked area.

HANDLE hFile;

HANDLE hAppend;

DWORD dwBytesRead, dwBytesWritten, dwPos;

char buff[4096];

/* Open existing file. */

hFile = CreateFile("ONE.TXT", /* open ONE.TXT */

GENERIC_READ, /* open for reading */

0, /* do not share */

(LPSECURITY_ATTRIBUTES) NULL, /* no security */

OPEN_EXISTING, /* existing file only */

FILE_ATTRIBUTE_NORMAL, /* normal file */

(HANDLE) NULL); /* no attr template */

if (hFile == INVALID_HANDLE_VALUE) {

ErrorHandler("Could not open ONE."); /* process err on fail*/

}

/*

* Open existing file or, if file doesn't exist,

* create new file.

*/

hAppend = CreateFile("TWO.TXT", /* open TWO.TXT */

GENERIC_WRITE, /* open for writing */

0, /* do not share */

(LPSECURITY_ATTRIBUTES) NULL, /* no security */

OPEN_ALWAYS, /* open or create */

FILE_ATTRIBUTE_NORMAL, /* normal file */

(HANDLE) NULL); /* no attr template */

if (hAppend == INVALID_HANDLE_VALUE) {

ErrorHandler("Could not open TWO."); /* process err on fail*/

}

/*

* Append the first file to the end of the second file.

* Lock the second file to prevent another process from

* accessing it while we're writing to it. Unlock the

* file when we're finished writing.

*/

do {

if (ReadFile(hFile, (LPSTR) buff, 4096, &dwBytesRead, NULL)) {

dwPos = SetFilePointer(hAppend, 0, (LPLONG) NULL, FILE_END);

LockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);

WriteFile(hAppend, (LPSTR) buff, dwBytesRead,

&dwBytesWritten, NULL);

UnlockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);

}

} while (dwBytesRead == 4096);

/* Close both files. */

CloseHandle(hFile);

CloseHandle(hAppend);