Question

Je suis en train de créer une application de téléchargement et je souhaite préallouer de la place sur le disque dur pour les fichiers avant qu'ils ne soient réellement téléchargés, car ils pourraient potentiellement être assez volumineux, et que personne n'aime voir "Ce disque est plein, supprimez certains fichiers. et essayez à nouveau. " Donc, à la lumière de cela, j’ai écrit ceci.

// Quick, and very dirty
System.IO.File.WriteAllBytes(filename, new byte[f.Length]);

Cela fonctionne, du moins jusqu’à ce que vous téléchargiez un fichier de plusieurs centaines de Mo, voire même de plusieurs Go, et que vous jetiez Windows dans une frénésie débordante, voire que vous n’effaciez pas totalement le fichier d'échange et que la mémoire de votre système ne soit totalement détruite. Oops.

Alors, avec un peu plus de lumière, je suis parti avec l'algorithme suivant.

using (FileStream outFile = System.IO.File.Create(filename))
{
    // 4194304 = 4MB; loops from 1 block in so that we leave the loop one 
    // block short
    byte[] buff = new byte[4194304];
    for (int i = buff.Length; i < f.Length; i += buff.Length)
    {
        outFile.Write(buff, 0, buff.Length);
    }
    outFile.Write(buff, 0, f.Length % buff.Length);
}

Cela fonctionne, même bien, et ne souffre pas du problème de mémoire paralysant de la dernière solution. Cela reste néanmoins lent, en particulier sur les matériels plus anciens, car ils écrivent (potentiellement des Go) des données sur le disque.

La question est la suivante: existe-t-il un meilleur moyen de réaliser la même chose? Existe-t-il un moyen de dire à Windows de créer un fichier de taille x et d'allouer simplement de l'espace sur le système de fichiers plutôt que d'écrire une tonne de données. Peu m'importe d'initialiser les données dans le fichier (le protocole que j'utilise - bittorrent - fournit des hachages pour les fichiers qu'il envoie, donc le pire cas pour des données aléatoires non initialisées est que je reçois une coïncidence chanceuse et une partie du fichier est correct).

Était-ce utile?

La solution

FileStream.SetLength est celui que vous souhaitez . La syntaxe:

public override void SetLength(
    long value
)

Autres conseils

Si vous devez créer le fichier, je pense que vous pouvez probablement faire quelque chose comme ceci:

using (FileStream outFile = System.IO.File.Create(filename))
{
    outFile.Seek(<length_to_write>-1, SeekOrigin.Begin);
    OutFile.WriteByte(0);
}

Où length_to_write serait la taille en octets du fichier à écrire. Je ne suis pas sûr d'avoir la syntaxe C # correcte (pas sur un ordinateur à tester), mais j'ai déjà fait des choses similaires en C ++ et cela a fonctionné.

Malheureusement, vous ne pouvez pas vraiment faire cela en cherchant jusqu'au bout. Cela définira la longueur du fichier sur quelque chose d'énorme, mais ne permettra pas réellement d'allouer des blocs de disque pour le stockage. Ainsi, lorsque vous écrivez le fichier, il échouera toujours.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top