MSDN Documentation

Windows API Reference

File Streams

This section provides detailed information about the Windows API functions and structures related to file stream operations. File streams offer a more abstract and powerful way to interact with files compared to traditional file handles, allowing for asynchronous operations, buffering, and advanced control over data flow.

Introduction to File Streams

File streams in Windows leverage technologies like the Asynchronous I/O (AIO) model and the I/O Completion Ports (IOCP) for high-performance, scalable file operations. They are particularly useful in server applications and scenarios requiring efficient handling of large files or a high volume of concurrent I/O requests.

Key Concepts

Core API Functions

Creating and Opening Streams

Functions to create new files or open existing ones for stream-based access.

  • CreateStreamOnFile

    Creates or opens a file for stream-based access. This function is a modern replacement for older Win32 file creation functions.

    HRESULT CreateStreamOnFile(PCWSTR pszFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, IStream **ppstm);
  • CreateFile2

    A more robust and feature-rich version of CreateFile that can be used to create file stream objects.

    HANDLE CreateFile2(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams);

Reading and Writing Data

Functions for performing asynchronous and synchronous read and write operations.

  • ReadFile

    Reads data from a file or device into a buffer. Can be used asynchronously.

    BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
  • WriteFile

    Writes data from a buffer to a file or device. Can be used asynchronously.

    BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
  • ReadClassStream

    Reads object data from a stream.

    HRESULT ReadClassStream(IStream *pstm, CLSID *pclsid);
  • WriteClassStream

    Writes object data to a stream.

    HRESULT WriteClassStream(IStream *pstm, REFCLSID rclsid);

Seeking and Positioning

Functions to move the read/write pointer within the file stream.

  • SetFilePointerEx

    Moves the file pointer to a specified location within a file.

    BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
  • Seek

    Moves the seek pointer of the stream to a specified position.

    HRESULT Seek(IStream *pstm, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition);

Stream Properties and Control

Functions to get information about the stream and manage its state.

  • GetFileSizeEx

    Retrieves the size of the specified file.

    BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
  • SetEndOfFile

    Sets the specified file to the specified size.

    BOOL SetEndOfFile(HANDLE hFile);
  • LockFileEx

    Locks a specified portion of a file for exclusive access.

    BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockHigh, DWORD nNumberOfBytesToLockLow, LPOVERLAPPED lpOverlapped);

Using Streams with COM

The IStream interface is a fundamental part of COM that represents a stream of bytes. Many COM objects use IStream for serialization and data transfer. Understanding how to implement and use IStream is crucial for advanced COM programming.

Example: Reading from a Memory Stream


#include <windows.h>
#include <objbase.h>
#include <stdio.h>

// Assume IStream is already defined and available

int main() {
    IStream *pStream = NULL;
    ULARGE_INTEGER ulSize;
    HRESULT hr;

    // Create a memory stream (e.g., using SHCreateMemStream)
    // For simplicity, let's assume pStream is already initialized with some data

    // Get the size of the stream
    if (SUCCEEDED(pStream->Seek(0, STREAM_SEEK_END, &ulSize))) {
        printf("Stream size: %llu bytes\n", ulSize.QuadPart);
    }

    // Reset stream position to the beginning
    if (SUCCEEDED(pStream->Seek(0, STREAM_SEEK_SET, NULL))) {
        // Read data from the stream
        char buffer[100];
        ULONG bytesRead;
        hr = pStream->Read(buffer, sizeof(buffer) - 1, &bytesRead);

        if (SUCCEEDED(hr) && bytesRead > 0) {
            buffer[bytesRead] = '\0'; // Null-terminate the buffer
            printf("Read from stream: %s\n", buffer);
        } else if (hr == S_FALSE) {
            printf("End of stream reached.\n");
        } else {
            printf("Error reading from stream: HRESULT = %08X\n", hr);
        }
    }

    // Release the stream
    if (pStream) {
        pStream->Release();
    }

    return 0;
}
            

Best Practices