In einem Tool, das große Dateien zwischen den Festplatten kopiert, ersetzte ich die System.IO.FileInfo.CopyTo-Methode durch System.IO.Stream.CopyToAsync. Dies ermöglicht eine schnellere Kopie und eine bessere Kontrolle während der Kopie, z. Ich kann die Kopie stoppen. Aber das erzeugt noch mehr Fragmentierung der kopierten Dateien. Es ist besonders ärgerlich, wenn ich Dateien von mehreren hundert Megabyte kopiere.C# I/O async (copyAsync): Wie kann Dateifragmentierung vermieden werden?
Wie kann ich Datenträgerfragmentierung während der Kopie vermeiden?
Mit dem Befehl xcopy kopiert die Option/j Dateien ohne Pufferung. Und es wird in für sehr große Datei empfohlen TechNet Es scheint in der Tat Dateifragmentierung zu vermeiden (während einer einfache Kopieren von Dateien in Windows 10 Explorer meine Datei nicht fragmentieren!)
Eine Kopie ohne Pufferung die entgegengesetzte Richtung als dies zu sein scheint asynchrone Kopie. Oder gibt es eine Möglichkeit, Async-Kopie ohne Pufferung zu tun?
Hier ist es mein derzeitiger Code für eine sync Kopie. Ich lasse die Standardpuffergröße von 81920 Bytes, d.h. 10 * 1024 * Größe (int64).
Ich arbeite mit NTFS-Dateisystemen, also 4096 Bytes Cluster.
EDIT: ich den Code mit SetLength aktualisiert, wie vorgeschlagen, fügte der Fileoptions Async während die destinationStream Erstellen und fixieren Sie die Attribute nach dem Einstellen der Zeiteinstellung
(sonst Ausnahme für Readonly-Dateien ausgelöst wird) 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!
}
I Fürchte auch, dass die File.SetAttributes und die Zeit am Ende meines Codes die Dateifragmentierung erhöhen könnten.
Gibt es einen richtigen Weg, um eine 1: 1 asynchrone Dateikopie ohne Dateifragmentierung zu erstellen, d. H. Die Festplatte fragt, ob die Datei nur zusammenhängende Sektoren erhält?
Andere Themen in Bezug auf Dateifragmentierung wie How can I limit file fragmentation while working with .NET schlägt vor, die Dateigröße in größeren Blöcken zu erhöhen, aber es scheint keine direkte Antwort auf meine Frage zu sein.
Haben Sie versucht 'destinationStream.Length = sourceStream.Length' kurz vor dem Kopieren? –
Gute Idee, Länge ist nur ein Getter, aber die SetLength-Methode macht den Job. Es scheint in der Tat Fragmentierung bei einem schnellen Test zu vermeiden! Ich sehe auch die FileOptions beim Erstellen des DestinationStream. Frage mich, ob Asynchronous oder WriteThrough eine gute Option sein könnte – EricBDev