在一个用于磁盘间拷贝大文件的工具中,我将 System.IO.FileInfo.CopyTo 方法替换成了 System.IO.Stream.CopyToAsync。这样可以实现更快的拷贝和更好的控制,例如我可以停止拷贝。但这会导致被拷贝文件更加碎片化。当我拷贝数百兆字节大小的文件时,这尤其令人烦恼。
如何避免拷贝过程中的磁盘碎片化?
使用 xcopy 命令,/j 开关可以无缓存地拷贝文件。对于非常大的文件,TechNet 推荐使用该开关。它似乎确实可以避免文件碎片化(而在 Windows 10 资源管理器中进行简单的文件拷贝却会导致文件碎片化!)
无缓存的拷贝似乎与异步拷贝背道而驰。是否有办法实现异步拷贝且不使用缓存?
以下是我的当前异步拷贝代码。我使用默认的缓冲区大小,即 81920 字节,即 10*1024*size(int64)。
我正在使用 NTFS 文件系统,因此每个簇的大小为 4096 字节。
我担心我的代码末尾的File.SetAttributes和Time可能会增加文件碎片化。
有没有一种正确的方法来创建一个1:1的异步文件复制而不会产生任何文件碎片,即请求HDD使文件流仅获得连续扇区?
关于文件碎片化的其他主题,例如如何在使用.NET时限制文件碎片化建议以较大的块递增文件大小,但这似乎并不是我问题的直接答案。
如何避免拷贝过程中的磁盘碎片化?
使用 xcopy 命令,/j 开关可以无缓存地拷贝文件。对于非常大的文件,TechNet 推荐使用该开关。它似乎确实可以避免文件碎片化(而在 Windows 10 资源管理器中进行简单的文件拷贝却会导致文件碎片化!)
无缓存的拷贝似乎与异步拷贝背道而驰。是否有办法实现异步拷贝且不使用缓存?
以下是我的当前异步拷贝代码。我使用默认的缓冲区大小,即 81920 字节,即 10*1024*size(int64)。
我正在使用 NTFS 文件系统,因此每个簇的大小为 4096 字节。
编辑:根据建议,我更新了代码并使用SetLength添加了FileOptions Async,同时在创建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使文件流仅获得连续扇区?
关于文件碎片化的其他主题,例如如何在使用.NET时限制文件碎片化建议以较大的块递增文件大小,但这似乎并不是我问题的直接答案。
destinationStream.Length = sourceStream.Length;
吗? - Lucas Trzesniewski