File Management Program Examples
The following samples use the file management functions:
Appending One File to Another File Program Example
The following code example shows you how to open and close files, read and write to files, and lock and unlock files. In the example, the application appends one file to the end of another file. First, the application opens the file being appended with permissions that allow only the application to write to it. However, during the append process other processes can open the file with read-only permission, which provides a snapshot view of the file being appended. Then, the file is locked during the actual append process to ensure the integrity of the data being written to the file. This example does not use transactions. If you were using transacted operations, you would only be able have read-only access. In this case, you would only see the appended data after the transaction commit operation completed. The example also shows that the application opens two files by using CreateFile():
Then the application uses ReadFile() and WriteFile() to append the contents of testcreatefile1.txt to the end of testcreatefile2.txt by reading and writing the 4K blocks. However, before writing to the second file, the application uses SetFilePointer() to set the pointer of the second file to the end of that file, and uses LockFile() to lock the area to be written. This prevents another thread or process with a duplicate handle from accessing the area while the write operation is in progress. When each write operation is complete, UnlockFile() is used to unlock the locked area.
Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.
Then, add the source file and give it a suitable name.
Next, add the following source code.
#include <windows.h>
#include <stdio.h>
// A safer version for string manipulation
#include <strsafe.h>
// A prototype that receives a function name, displaying
// system error code and its respective message
void DisplayErrorBox(LPTSTR lpszFunction);
int wmain(int argc, WCHAR *argv[])
{
HANDLE hFile;
HANDLE hAppend;
LPWSTR pFileName1 = LC:\\testcreatefile1.txt;
LPWSTR pFileName2 = Ltestcreatefile2.txt;
DWORD dwBytesRead, dwBytesWritten, dwPos;
BYTE buff[4096];
// Open the existing file
hFile = CreateFile(pFileName1, // open testcreatefile1.txt
GENERIC_READ, // open for reading
0, // do not share
NULL, // no security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
DisplayErrorBox(LCreateFile() 1);
return 1;
}
else
wprintf(LCreateFile() 1 is OK. %s was opened successfully!\n, pFileName1);
// Open the existing file, or if the file does not exist, create a new file
hAppend = CreateFile(pFileName2, // open testcreatefile2.txt
FILE_APPEND_DATA, // open for writing
FILE_SHARE_READ, // allow multiple readers
NULL, // no security
OPEN_ALWAYS, // open or create
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hAppend == INVALID_HANDLE_VALUE)
{
DisplayErrorBox(LCreateFile() 2);
return 1;
}
else
wprintf(LCreateFile() 2 is OK. %s was created & opened successfully!\n, pFileName2);
// Append the first file to the end of the second file.
// Lock the second file to prevent another process from
// accessing it while writing to it. Unlock the file when writing is complete
wprintf(LReading %s file content...\n, pFileName1);
while (ReadFile(hFile, buff, sizeof(buff), &dwBytesRead, NULL)&& dwBytesRead > 0)
{
dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
wprintf(LSetFilePointer() returns %u\n, dwPos);
if(LockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
wprintf(LLockFile() is pretty fine!\n);
else
DisplayErrorBox(LLockFile());
if(WriteFile(hAppend, buff, dwBytesRead, &dwBytesWritten, NULL) != 0)
wprintf(LWriteFile() is pretty fine!\n);
else
DisplayErrorBox(LWriteFile());
if(UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0) != 0)
wprintf(LUnlockFile() is pretty fine!\n);
else
DisplayErrorBox(LUnlockFile());
}
// Close both files.
if(CloseHandle(hFile) != 0)
wprintf(LClosing hFile handle!\n);
else
DisplayErrorBox(LCloseHandle(hFile));
if(CloseHandle(hAppend) != 0)
wprintf(LClosing hAppend handle!\n);
else
DisplayErrorBox(LCloseHandle(hAppend));
return 0;
}
void DisplayErrorBox(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and clean up
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(WCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(WCHAR), L%s failed with error %d: %s, lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, LError, MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
Build and run the project. The following screenshot is a sample output when the first file cannot be found.

Create a text file named testcreatefile1.txt, write some text and save it in the root C: drive.

Next, we re-run the project.


Well, there are errors. However, when we re-run the program second times, those errors disappeared.

The second file was created successfully under the project's folder as shown below.

Then, re-run the program again so that the second run will append the first file's content to the second file.

Then, open the testcreatefile2.txt. We can see in testcreatefile2.txt that the content of testcreatefile1.txt was appended.
