在磁盘之间复制大文件的工具中,我用System.IO.Stream.CopyToAsync替换了System.IO.FileInfo.CopyTo方法中的 。 这允许在拷贝期间更快的拷贝和更好的控制,例如,我可以停止复制。 但是这会造成复制文件的更多碎片化。当我复制数百兆字节的文件时尤其令人讨厌。C#I/O异步(copyAsync):如何避免文件碎片?
如何在复制过程中避免磁盘碎片?
使用xcopy命令,/ j开关复制文件而不缓冲。它被推荐用于非常大的文件中TechNet 这似乎的确避免文件碎片(而窗内一个简单的文件副本10 Explorer支持分段我的档案!)
没有缓冲副本似乎比这个相反的方式异步拷贝。或者有没有办法异步复制而不缓冲?
这里它是我当前的代码异步复制。我让默认的缓冲区大小为81920字节,即10 * 1024 *大小(int64)。
我正在使用NTFS文件系统,因此有4096个字节的簇。
编辑:我更新中用SetLength函数的代码的建议,增加了FileOptions异步在创建destinationStream和修复设置属性后设定的时间(否则,抛出异常的只读文件)
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,建议以较大的块增加文件大小,但似乎并不直接回答我的问题。
你试过'destinationStream.Length = sourceStream.Length;'就在复制之前? –
好主意,长度只是一个吸气剂,但SetLength方法完成这项工作。看起来真的要在快速测试中避免分裂! 我在创建destinationStream时也看到了FileOptions。不知道是否异步或WriteThrough可能是一个不错的选择 – EricBDev