gpt4 book ai didi

C# I/O 异步 (copyAsync) : how to avoid file fragmentation?

转载 作者:行者123 更新时间:2023-11-30 14:48:29 27 4
gpt4 key购买 nike

在磁盘之间复制大文件的工具中,我替换了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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com