- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在磁盘之间复制大文件的工具中,我替换了System.IO.Stream.CopyToAsync 的 System.IO.FileInfo.CopyTo 方法。这允许在复制过程中进行更快的复制和更好的控制,例如我可以停止复制。但这会造成复制文件的更多碎片。当我复制数百兆字节的文件时尤其烦人。
复制时如何避免磁盘碎片?
使用 xcopy 命令,/j 开关复制文件而不缓冲。并且建议在 TechNet 中用于非常大的文件似乎确实可以避免文件碎片化(而 Windows 10 资源管理器中的简单文件复制确实会碎片化我的文件!)
没有缓冲的副本似乎与此异步副本相反。或者有什么方法可以在不缓冲的情况下进行异步复制?
这是我当前的 aync 复制代码。我让默认缓冲区大小为 81920 字节,即 10*1024*size(int64)。
我正在使用 NTFS 文件系统,因此是 4096 字节的簇。
编辑:我按照建议使用 SetLength 更新了代码,在创建 destinationStream 时添加了 FileOptions Async,并在设置时间后修复设置属性(否则,ReadOnly 文件会抛出异常)
int bufferSize = 81920;
try
{
using (FileStream sourceStream = source.OpenRead())
{
// Remove existing file first
if (File.Exists(destinationFullPath))
File.Delete(destinationFullPath);
using (FileStream destinationStream = File.Create(destinationFullPath, bufferSize, FileOptions.Asynchronous))
{
try
{
destinationStream.SetLength(sourceStream.Length); // avoid file fragmentation!
await sourceStream.CopyToAsync(destinationStream, bufferSize, cancellationToken);
}
catch (OperationCanceledException)
{
operationCanceled = true;
}
} // properly disposed after the catch
}
}
catch (IOException e)
{
actionOnException(e, "error copying " + source.FullName);
}
if (operationCanceled)
{
// Remove the partially written file
if (File.Exists(destinationFullPath))
File.Delete(destinationFullPath);
}
else
{
// Copy meta data (attributes and time) from source once the copy is finished
File.SetCreationTimeUtc(destinationFullPath, source.CreationTimeUtc);
File.SetLastWriteTimeUtc(destinationFullPath, source.LastWriteTimeUtc);
File.SetAttributes(destinationFullPath, source.Attributes); // after set time if ReadOnly!
}
我还担心代码末尾的 File.SetAttributes 和 Time 会增加文件碎片。
是否有正确的方法来创建没有任何文件碎片的 1:1 异步文件副本,即要求 HDD 文件流仅获取连续的扇区?
关于文件碎片的其他主题,如 How can I limit file fragmentation while working with .NET建议以更大的 block 增加文件大小,但这似乎不是我问题的直接答案。
最佳答案
but the SetLength method does the job
它不做这项工作。它仅更新目录条目中的文件大小,它不分配任何簇。亲自查看此内容的最简单方法是在非常大的文件(例如 100 GB)上执行此操作。请注意调用是如何立即完成的。只有当文件系统不执行分配和写入集群的工作时,它才能立即完成。从文件中读取实际上是可能的,即使文件不包含实际数据,文件系统也只是返回二进制零。
这也会误导任何报告碎片的实用程序。由于该文件没有簇,因此不会有碎片。所以看起来你只是解决了你的问题。
要强制分配簇,您唯一可以做的就是实际写入文件。事实上,一次写入就可以分配 100 GB 的集群。您必须使用 Seek() 定位到 Length-1,然后使用 Write() 写入一个字节。对于非常大的文件,这将需要一段时间,它实际上不再是异步的。
它减少碎片化的可能性不大。您只是在某种程度上降低了写入将被其他进程的写入交错的风险。某种程度上,实际写入是由文件系统缓存延迟完成的。核心问题是在您开始写入之前该卷是碎片化的,在您完成后它永远不会碎片化。
最好的办法就是不要为此烦恼。这些天在 Windows 上进行碎片整理是自动的,自 Vista 以来一直如此。也许你想 play with the scheduling , 也许您想在 superuser.com 上询问更多相关信息
关于C# I/O 异步 (copyAsync) : how to avoid file fragmentation?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41494542/
我是一名优秀的程序员,十分优秀!