我知道有时在复制文件时,系统会“缓存”复制过程,或者“延迟”该过程:即,复制过程实际完成比“过程完成”UI 需要更长的时间-通知会让你相信。这就是为什么在复制到外部硬盘驱动器后立即直接删除它们并不好,而是要稍等一下再这样做。
因此,现在假设我将文件复制到同一驱动器内的另一个文件夹,或者完全复制到不同的驱动器。现在,我立即将该源文件移动到另一个文件夹,或者删除它(将其移动到垃圾箱);就文件损坏而言,这样做会危及源文件或其新制作的副本吗?或者更确切地说,计算机是否有一个适当的系统来防止这种可能性,通过在复制完全完成之前自动防止源文件的任何实际移动或删除?
这是一个相当重要的区别,因为不同的驱动器意味着不同的文件系统,很可能具有不同的存储语义、缓存行为等。因此,让我们让事情变得更简单,并保留在同一个文件系统中。
由于您的重点是 Windows,所以答案是肯定的。Windows 实现了一种方法,即应用程序在默认情况下对文件执行某些操作时独占锁定这些文件,以便其他应用程序无法访问它。对文件执行某些操作的第一个应用程序需要决定允许其他应用程序执行哪些操作、读取、写入、删除等。如果没有明确的决定,其他应用程序将无法执行任何操作,包括在复制过程中移动文件。请记住,复制过程是一个应用程序,试图同时将文件移动到另一个应用程序等。有关详细信息,请查看CreateFileW及其参数
dwShareMode
。因此,虽然有某种程度的可用安全网,但这很可能是不需要的:无论如何,文件系统缓存(大部分)是由操作系统和文件系统透明处理的。总体目标是用户和应用程序不需要处理细节,其中包括复制和了解数据何时真正复制以进行进一步操作之类的事情。应用程序可能对此类细节感兴趣,例如可能使用刷新命令,这些命令告诉操作系统或文件系统它们现在将缓存写入某些文件的数据,并且调用应用程序等待直到完成。但在大多数情况下这是没有必要的。
这包括复制后移动:如果仅涉及文件系统缓存,而不涉及文件系统缓存,例如文件仍被复制过程本身锁定(例如 Windows 资源管理器),则即使尚未将所有数据写入磁盘,您也可以自由移动文件。这是因为大多数文件系统并不直接将实际文件数据与其文件名或路径相关联,而是独立处理两者。因此,数据存储在某个位置,在不同的位置存储文件名,引用其父路径并引用数据。因此,当文件名本身更改或移动到其他目录时,它只是保留对实际数据的引用,操作系统和文件系统可以同时继续将其缓存刷新到它们已经关联的位置文件名。
https://en.wikipedia.org/wiki/Inode
现代文件系统甚至不需要关心或事先知道需要写入多少数据,它们只是按照一定的规则在某处分配数据块,并将每个分配的块与已经存在的填充名称对象相关联。
https://en.wikipedia.org/wiki/Extent_(file_systems)
以上都不是。此时文件复制过程不依赖于原始文件;它已经读取了所有原始文件并将所有数据“写入”到新文件中,因此“处理完成”UI 通知有点告诉您真相。
实际上被缓存(缓冲)的只是那些写操作——有一个完全独立的缓存层,与复制无关,而是与一般写入磁盘有关。任何文件写入,无论是从一个文件复制到另一个文件还是只是保存文档,都会首先由操作系统缓冲在内存中,然后才刷新到物理存储。(也就是说,就程序所见而言,数据已经“在”文件中,只是还没有在磁盘上的文件中。)
在同一文件系统(分区)内或不同文件系统之间移动之间存在细微差别。
对于在同一文件系统内移动:磁盘上的文件数据与其文件表内的元数据完全分开。元数据包括指向数据的指针,但与数据无关,因为可以将文件条目移动到另一个文件夹而不移动数据。
在您的情况下,可能发生的情况是文件的数据尚未终止移动并且仍在缓存内,而文件条目已移动到同一文件系统中的其他位置。不会遇到任何问题,并且文件的数据将继续从缓存中刷新,而文件已经位于其新文件夹中(包括当这是回收站时)。
对于在不同文件系统内移动:Windows 将尝试将文件的数据复制到新磁盘,然后创建并输入新的文件表,最后删除源磁盘上的文件。
复制数据时,每个源块将依次被读取和复制。如果源数据尚未写入源磁盘中的位置,则可以从内存缓存中读取源数据,然后将其复制到新磁盘。例如,很可能会发现相同的数据在缓存中重复两次,其中每个副本都注定要写入不同的磁盘。
当 Windows 的复制操作完成时,即使没有将所有块都写入两个磁盘,源文件也会被删除。这将使内存缓存中的所有块无效,从而简单地取消源文件中未写入的块。在这种情况下,可能会发生这样的情况:立即删除或移动文件最终在磁盘上比等待写入终止后再执行操作更有效。
对于复制后立即删除:如上所述,这将取消内存缓存中仍存在的所有未写入块,因此此类块永远不会写入磁盘。