Domanda

Sto creando un'applicazione di download e desidero preallocare spazio sul harddrive per i file prima che vengano effettivamente scaricati in quanto potrebbero essere potenzialmente piuttosto grandi e a nessuno piace vedere "Questa unità è piena, per favore elimina alcuni file e riprova. " Quindi, in quella luce, ho scritto questo.

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

Funziona, almeno finché non scarichi un file di diverse centinaia di MB, o potenzialmente anche GB e getti Windows in una frenesia frenetica se non cancelli completamente il file di paging e uccidi del tutto la memoria del tuo sistema.Ops.

Quindi, con un po’ più di illuminazione, ho iniziato con il seguente algoritmo.

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);
}

Funziona, anche bene, e non soffre del paralizzante problema di memoria dell'ultima soluzione.Tuttavia è ancora lento, soprattutto su hardware più vecchio poiché scrive dati (potenzialmente GB) sul disco.

La domanda è questa:Esiste un modo migliore per ottenere la stessa cosa?Esiste un modo per dire a Windows di creare un file di dimensione x e allocare semplicemente lo spazio sul filesystem anziché scrivere effettivamente una tonnellata di dati.Non mi interessa affatto inizializzare i dati nel file (il protocollo che sto utilizzando - bittorrent - fornisce hash per i file che invia, quindi il caso peggiore per dati casuali non inizializzati è che ottengo una coincidenza fortunata e parte del file è corretta).

È stato utile?

Soluzione

FileStream.SetLength è quello che vuoi.La sintassi:

public override void SetLength(
    long value
)

Altri suggerimenti

Se devi creare il file, penso che probabilmente potresti fare qualcosa del genere:

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

Dove lunghezza_da_scrivere sarebbe la dimensione in byte del file da scrivere.Non sono sicuro di avere la sintassi C# corretta (non su un computer per testarla), ma in passato ho fatto cose simili in C++ e ha funzionato.

Sfortunatamente, non puoi farlo davvero solo cercando fino alla fine.Ciò imposterà la lunghezza del file su qualcosa di enorme, ma potrebbe non allocare effettivamente i blocchi del disco per l'archiviazione.Quindi quando vai a scrivere il file, fallirà comunque.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top