阅读和写入文件

【勇芳软件工作室】汉化HomePreviousNext

每个打开的文件都有一个【文件指针】,指定要读取的下一个字节或接收下一个字节的位置。首次打开文件时,Windows会将文件指针放在文件的开头。当读取或写入每个字节时,Windows将前进文件指针。应用程序也可以使用SetFilePointer功能移动文件指针。

应用程序使用ReadFileWriteFile功能读取和写入文件。这些功能需要分别打开文件的句柄以进行读写。ReadFileWriteFile在文件指针指示的位置读取和写入指定的字节数。数据按照给定的方式读取和写入;功能不格式化数据。

当文件指针到达文件的末尾,应用程序尝试从文件中读取时,不会发生错误,但不会读取字节。因此,读取零字节没有错误意味着程序已经到达文件的末尾。写零字节什么都不做。

应用程序可以使用SetEndOfFile功能截断或扩展文件。该函数将文件的结尾设置为文件指针的当前位置。

当应用程序写入文件时,Windows通常会收集正在写入内部缓冲区的数据,并将数据定期写入磁盘。

应用程序可以强制操作系统使用FlushFileBuffers功能将缓冲区的内容写入磁盘。或者,应用程序可以指定写入操作绕过内部缓冲区,并通过使用CreateFile功能创建或打开文件时设置标志,直接写入磁盘。

如果文件关闭时内部缓冲区中有数据,则在关闭文件之前,Windows不会将缓冲区的内容自动写入磁盘。如果应用程序在关闭文件之前不强制操作系统将缓冲区写入磁盘,则缓存算法确定缓冲区何时写入。

在读取操作完成之前,应用程序不得从读取操作正在读取或写入输入缓冲区。对输入缓冲区的过早访问可能导致读入该缓冲区的数据损坏。

锁定和解锁文件

虽然Windows允许多个应用程序打开一个文件并写入它,但是应用程序不能写在对方的工作中。应用程序可以通过临时锁定文件中的区域来防止此问题。LockFileLockFileEx功能锁定文件中指定的字节范围。范围可能会超出文件的当前结尾。锁定文件的一部分可防止所有其他进程在指定区域的任何位置读取或写入。尝试从另一个进程锁定的区域读取或写入总是失败。

LockFileEx功能允许应用程序指定【共享锁】【专属锁】.排他锁拒绝所有其他进程对文件的指定区域的读取和写入访问。共享锁拒绝所有进程对文件的指定区域的写入访问,包括首先锁定该区域的进程。这可以用于在文件中创建只读区域。

应用程序使用UnlockFileUnlockFileEx功能解锁该区域。在关闭文件之前,应用程序应该解锁所有的锁定区域。

异步输入和输出

【异步输入和输出】(异步I / O)允许一些I / O功能立即返回,即使I / O请求仍在等待。异步I / O使应用程序能够继续其他处理,并等待稍后完成I / O。异步I / O也称为重叠I / O。

ReadFileWriteFile功能使应用程序能够指定一个OVERLAPPED结构,指示在读取或写入操作之前将文件指针放在何处。正在读取或写入的文件的句柄必须使用FILE_FLAG_OVERLAPPED标志打开。您还可以创建一个事件并将句柄放在OVERLAPPED结构中;然后可以通过等待事件句柄来使用等待功能等待I / O操作完成。

应用程序还可以等待文件句柄来同步I / O操作的完成,但这样做需要非常小心。每次启动I / O操作时,操作系统将文件句柄设置为非信号状态。每次I / O操作完成时,操作系统将文件句柄设置为信号状态。因此,如果应用程序启动两个I / O操作并等待文件句柄,则当句柄设置为信号状态时,无法确定哪个操作已完成。如果应用程序必须在单个文件上执行多个异步I / O操作,则应等待每个I / O操作的OVERLAPPED结构中的事件句柄,而不是在文件句柄上。

要取消所有挂起的异步I / O操作,请使用CancelIO功能。此函数仅取消调用线程为指定的文件句柄发出的操作。

当异步I / O请求完成时,ReadFileExWriteFileEx函数使应用程序能够指定要执行的例程(参见FileIOCompletionRoutine)。

有关详细信息,请参阅同步和重叠输入和输出.

I / O完成端口

I / O完成端口与异步I / O一起使用。CreateIoCompletionPort函数将I / O完成端口与一个或多个文件句柄相关联。当在与I / O完成端口相关联的文件句柄上启动异步I / O操作完成时,I / O完成数据包将排队到端口。这可以用于将多个文件句柄的同步点组合成单个对象。

线程使用GetQueuedCompletionStatus功能等待I / O完成数据包排队到I / O完成端口,而不是直接等待异步I / O完成。在I / O完成端口上阻止其执行的线程以先进先出(LIFO)顺序发布。这意味着当I / O完成数据包排队到I / O完成端口时,系统释放最后一个线程以阻止其在端口上的执行。

I / O完成端口最重要的属性是并发值。创建I / O完成端口时,指定I / O完成端口的并发值。此值限制与I / O完成端口相关联的可运行线程的数量。当与I / O完成端口相关联的可运行线程的总数达到并发值时,系统将阻止线程的执行,直到与I / O完成端口相关联的可运行线程的数量低于并发值。当队列中有I / O完成数据包等待时,会发生最有效的方案,但由于端口已达到并发限制,因此不能满足等待状态。在这种情况下,当正在运行的线程调用GetQueuedCompletionStatus时,它将立即接收排队的I / O完成数据包。不会发生上下文切换,因为正在运行的线程不断拾取I / O完成数据包,而其他线程无法运行。

选择并发值的最佳值是机器上的CPU数量。如果您的事务需要冗长的计算,则较大的并发值将允许更多的线程运行。每笔交易需要更长时间才能完成,但会同时处理更多的交易。很容易对并发值进行实验,以达到最佳效果。

PostQueuedCompletionStatus功能允许应用程序将其自己的专用I / O完成数据包排队到I / O完成端口,而不启动异步I / O操作。这对通知工作线程的外部事件非常有用。

当没有更多的引用时,I / O完成端口被释放。端口句柄和与I / O完成端口相关联的每个文件句柄引用I / O完成端口。必须关闭所有手柄以释放I / O完成端口。要关闭端口句柄,请调用CloseHandle功能。