Reading, Writing, and Locking Files
The
ReadFile function requires a file handle that is open for reading, or reading and
writing.
ReadFile copies a specified number of bytes, from the current position up to the end
of the file, to a specified buffer. The current position is either the current
file pointer setting or the
Offset and
OffsetHigh members of the specified
OVERLAPPED structure. The function returns the actual number of bytes read in a variable
specified by its fourth parameter.
The
WriteFile function requires a file handle that is open for writing, or writing and
reading.
WriteFile copies a specified number of bytes, from the current position up to the end
of the buffer, to a specified file. The function returns the actual number of
bytes written in a variable specified by its fourth parameter.
The following example illustrates a possible flow for using callback
completion asynchronous I/O.
Completion Routine:
VOID IoCompletionRoutine(DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
// If an I/O error occurs, display the error and exit.
if (dwErrorCode) {
printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
dwErrorCode, lpOverlapped, lpOverlapped->hEvent);
ExitProcess(dwErrorCode);
}
LocalFree(lpOverlapped);
}
Main Thread:
VOID IoWorkerThread(VOID)
{
HANDLE HandleVector[2];
DWORD CompletionStatus;
PIOREQUEST IoRequestPacket;
LPOVERLAPPED Overlapped;
BOOL IoOperationStatus;
HandleVector[0] = IoWorkerListLock;
HandleVector[1] = IoWorkerListSemaphore;
for(;;) {
// Do an alertable wait on the handle vector.
Both objects
// being signaled at the same time means that there is an
// I/O request in the queue and the caller has exclusive
// access to the queue.
CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector,
TRUE, INFINITE, TRUE);
// If the wait failed, error out.
if (CompletionStatus == 0xFFFFFFFF) {
printf("FATAL WAIT ERROR %ld\n", GetLastError());
ExitProcess(1);
}
// If an I/O completion occurred, wait for another
// I/O request or I/O completion.
if (CompletionStatus != WAIT_IO_COMPLETION) {
// The wait was satisfied. Ownership of the I/O
// request queue is exclusive, and there is something in
// the queue. To insert something in the queue, the
// inserter gets the list lock (mutex), inserts an entry,
// signals the list semaphore, and finally releases the
// list lock.
IoRequestPacket = RemoveHeadList(&IoRequestList);
ReleaseMutex(IoWorkerListLock);
// Allocate an overlapped structure.
Overlapped = LocalAlloc(LMEM_ZEROINIT,
sizeof(OVERLAPPED));
if (!Overlapped) {
printf("FATAL allocation error\n");
ExitProcess(1);
}
Overlapped->Offset = IoRequestPacket->Offset;
Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh;
Overlapped->hEvent =
IoRequestPacket->dwAdditionalIoContext;
if (IoRequestPacket->bRead) {
IoOperationStatus =
ReadFileEx(IoRequestPacket->hFile,
IoRequestPacket->lpBuffer,
IoRequestPacket->dwTransferCount,
Overlapped, IoCompletionRoutine);
}
else {
IoOperationStatus =
WriteFileEx(IoRequestPacket->hFile,
IoRequestPacket->lpBuffer,
IoRequestPacket->dwTransferCount,
Overlapped,
IoCompletionRoutine);
}
// Test to see if the I/O was queued successfully.
if (!IoOperationStatus) {
printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
GetLastError(), Overlapped, Overlapped->hEvent);
ExitProcess(1);
}
// The I/O queued successfully. Go back into the
// alertable wait for I/O completion or for
// more I/O requests.
}
}
}
The
SetFilePointer function moves the file pointer a specified number of bytes, relative to the
beginning or end of the file, or the file pointer's current position. If a
positive number of bytes is specified,
SetFilePointer moves the file pointer toward the end of the file; a negative value moves the
pointer toward the beginning of the file.
The following example appends one file to the end of another file. The
application opens two files by using
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 by using
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 operation,
UnlockFile unlocks the locked area.
HANDLE hFile;
HANDLE hAppend;
DWORD dwBytesRead, dwBytesWritten, dwPos;
char buff[4096];
// Open the existing file.
hFile = CreateFile("ONE.TXT", // open ONE.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) {
ErrorHandler("Could not open ONE."); // process error
}
// Open the existing file, or if the file does not exist,
// create a new file.
hAppend = CreateFile("TWO.TXT", // open TWO.TXT
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // no security
OPEN_ALWAYS, // open or create
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hAppend == INVALID_HANDLE_VALUE) {
ErrorHandler("Could not open TWO."); // process error
}
// 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 finished.
do {
if (ReadFile(hFile, buff, 4096, &dwBytesRead, NULL)) {
dwPos = SetFilePointer(hAppend, 0, NULL, FILE_END);
LockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);
WriteFile(hAppend, buff, dwBytesRead,
&dwBytesWritten, NULL);
UnlockFile(hAppend, dwPos, 0, dwPos + dwBytesRead, 0);
}
} while (dwBytesRead == 4096);
// Close both files.
CloseHandle(hFile);
CloseHandle(hAppend);
- Software for developers
-
Delphi Components
.Net Components
Software for Android Developers
- More information resources
-
MegaDetailed.Net
Unix Manual Pages
Delphi Examples
- Databases for Amazon shops developers
-
Amazon Categories Database
Browse Nodes Database