DEV Community

Gurkirat Singh
Gurkirat Singh

Posted on

Windows System Programming: File I/O Operations

Hello There!

First of all, I am really sorry for taking a long time in writing this post. I have no reason / excuse to make for it.

What is not cool about programming is to not to learn how to deal with file operations. File operation are very handy when you have to read / write large data. You will first learn about writing into the file and then how to read from it.

The header file that will be used in Creating, Writing to File and Reading from File is fileapi.h

To write into a file, you need to first create a file. And this can be done by CreateFileA function.

HANDLE CreateFileA( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); 
Enter fullscreen mode Exit fullscreen mode

Functions parameters description as follows

  • lpFileName → The name of the file or device to be created or opened
  • dwDesiredAccess → The requested access to the file or device. The most commonly used values are GENERIC_READ, GENERIC_WRITE, or both (GENERIC_READ | GENERIC_WRITE). You can see the list of different types of access from here: GENERIC ACCESS RIGHTS | FILE ACCESS AND SECURITY RIGHTS | FILE ACCESS RIGHTS CONSTANTS
  • dwShareMode → The requested sharing mode of the file or device. Use 0x0, if you don't want to share this file.
  • lpSecurityAttributes → A pointer to a SECURITY_ATTRIBUTES structure. This parameter can be NULL
  • dwCreationDisposition → An action to take on a file or device that exists or does not exist. For devices other than files, this parameter is usually set to OPEN_EXISTING. The possible values can be ( CREATE_ALWAYS, CREATE_NEW, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING )
  • dwFlagsAndAttributes → The file or device attributes and flags, FILE_ATTRIBUTE_NORMAL being the most common default value for files. This parameter can also contain combinations of flags (FILE_FLAG_*)
  • hTemplateFile → A valid handle to a template file with the GENERIC_READ access right. This parameter can be NULL

NOTE: If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot

You have created the file, now writing to it can be done by WriteFile

BOOL WriteFile( HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped ); 
Enter fullscreen mode Exit fullscreen mode

Function parameters as follows

  • hFile → A handle to the file or I/O device with the write access.
  • lpBuffer → A pointer to the buffer containing the data to be written to the file or device.
  • nNumberOfBytesToWrite → The number of bytes to be written to the file or device.
  • lpNumberOfBytesWritten → A pointer to the variable that receives the number of bytes written when using a synchronous hFile parameter. This parameter can be NULL only when the lpOverlapped parameter is not NULL.
  • lpOverlapped → A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise this parameter can be NULL.

If the function succeeds, the return value is nonzero (TRUE).

After the data has been written, you should close the handle to flush all the data stored in the buffer into file.

Now comes, reading the file contents. You need to use ReadFile function.

BOOL ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped ); 
Enter fullscreen mode Exit fullscreen mode

Function parameters description as follows

  • hFile → A handle to the file or I/O device with the read access.
  • lpBuffer → A pointer to the buffer that receives the data read from a file or device.
  • nNumberOfBytesToRead → The maximum number of bytes to be read.
  • lpNumberOfBytesRead → A pointer to the variable that receives the number of bytes read. This parameter can be NULL only when the lpOverlapped parameter is not NULL.
  • lpOverlapped → A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_FLAG_OVERLAPPED, otherwise this parameter can be NULL.

If the function succeeds, the return value is nonzero (TRUE).

The complete code as follows

#include <Windows.h> #include <iostream> #include <fileapi.h> #include <string>  int main(int argc, char** argv) { if (argc == 1) { printf("usage: %s <filename>", argv[0]); return 1; } /* * Function Documentation * https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea */ HANDLE hFile = CreateFileA(argv[1], GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { switch (GetLastError()) { case ERROR_FILE_EXISTS: printf("File '%s' exists\n", argv[1]); break; default: printf("Error: %ul", GetLastError()); break; } return 1; } else { printf("File Created\n"); } // WRITING TO FILE std::string strBuff = "Hello World!! This is the file containing some random thought"; DWORD bytesToWrite = strBuff.size(), bytesWritten; // wrtiting buffer to file // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile BOOL bWrite = WriteFile(hFile, strBuff.c_str(), bytesToWrite, &bytesWritten, NULL); if (bWrite) { printf("Buffer written to file\n"); } else if (bytesToWrite != bytesWritten) { printf("Bytes written != bytes to write"); printf("\nSuccessfully wrote %d bytes to %s", bytesWritten, argv[1]); CloseHandle(hFile); return 1; } else { switch (GetLastError()) { default: printf("Error: WRITEFILE: %d\n", GetLastError()); CloseHandle(hFile); // closing file handle return 1; } } CloseHandle(hFile); // closing file handle // opening file handle to read the file hFile = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, // at this time the file already exists  FILE_ATTRIBUTE_NORMAL, NULL); DWORD nToRead = 15; // let's read 15 byts char chBuff[16]; DWORD nRead; // reading file // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile BOOL bRead = ReadFile(hFile, &chBuff, nToRead, &nRead, NULL); chBuff[15] = '\0'; // terminating string if (bRead) { printf("DATA: %s\n", chBuff); } else if (nToRead != nRead) { printf("Number of bytes to read != number of bytes read\n"); } else { switch (GetLastError()) { case ERROR_NOACCESS: printf("ERROR: No access to read file '%s'\n", argv[1]); break; default: printf("Error: READFILE: %d\n", GetLastError()); } CloseHandle(hFile); // closing file handle return 1; } CloseHandle(hFile); // closing file handle return 0; } 
Enter fullscreen mode Exit fullscreen mode

I hope you have enjoyed this post. Follow the links to reach me

Top comments (0)