File Handles

Understanding and working with file handles in Windows.

A file handle is an identifier that the operating system uses to refer to an open file or other I/O resource. When you open a file using functions like CreateFile, the system returns a handle that you can then use to perform operations on that file, such as reading, writing, or seeking.

Important: Always close file handles when you are finished with them by calling CloseHandle to release system resources. Failure to do so can lead to resource leaks and system instability.

Key Concepts

File handles are fundamental to Windows file operations. They represent an access token to a specific instance of an open file or device. Understanding their properties is crucial for efficient and safe file management.

Handle Attributes

When a handle is created, it can be associated with various attributes that define how the file can be accessed and managed. These include:

  • Access Rights: Specifies the type of access allowed (e.g., read, write, execute).
  • Sharing Mode: Determines how other processes can access the file concurrently.
  • Creation Disposition: Defines how the system should behave if the file already exists or does not exist.
  • Flags and Attributes: Additional flags that control file creation and open behavior, such as whether the file should be temporary or have specific security attributes.

Common File Handle Operations

The following table lists some of the most common Windows API functions used for managing file handles:

Function Description
CreateFile Creates or opens a file or device and returns a handle.
CloseHandle Closes an open object handle.
ReadFile Reads data from a file or I/O device into a buffer.
WriteFile Writes data from a buffer to a file or I/O device.
SetFilePointer Moves the file pointer to a specified location.
GetFileSizeEx Retrieves the size of the specified file.
DuplicateHandle Duplicates an existing handle to an object.

Example: Opening and Closing a File

Here's a simple C++ example demonstrating how to open a file for writing and then close its handle:


#include <windows.h>
#include <iostream>

int main() {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    const char* fileName = "example.txt";
    DWORD bytesWritten;
    const char* dataToWrite = "Hello, Windows API!\n";

    // Create or open the file for writing
    hFile = CreateFile(
        fileName,              // File name
        GENERIC_WRITE,         // Desired access
        0,                     // Share mode (exclusive access)
        NULL,                  // Security attributes
        CREATE_ALWAYS,         // Creation disposition
        FILE_ATTRIBUTE_NORMAL, // Flags and attributes
        NULL                   // Template file
    );

    if (hFile == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to create or open file. Error: " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "File '" << fileName << "' opened successfully." << std::endl;

    // Write data to the file
    if (!WriteFile(hFile, dataToWrite, strlen(dataToWrite), &bytesWritten, NULL)) {
        std::cerr << "Failed to write to file. Error: " << GetLastError() << std::endl;
        CloseHandle(hFile); // Clean up
        return 1;
    }

    std::cout << bytesWritten << " bytes written to file." << std::endl;

    // Close the file handle
    if (CloseHandle(hFile)) {
        std::cout << "File handle closed successfully." << std::endl;
    } else {
        std::cerr << "Failed to close file handle. Error: " << GetLastError() << std::endl;
        return 1;
    }

    return 0;
}
                
Best Practice: Use descriptive variable names for handles (e.g., hInputFile, hOutputFile) to improve code readability.

Further Reading