2008-09-19 11 views
14

Estoy creando una aplicación de descarga y deseo preasignar espacio en el disco duro para los archivos antes de que realmente se descarguen, ya que podrían ser bastante grandes, y a nadie le gusta ver "Esta unidad está llena, borre algunos archivos y pruebe de nuevo." Entonces, en esa luz, escribí esto.¿Espacio de archivo de preasignación en C#?

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

Funciona, al menos hasta que descargue un archivo que es de varios cientos de MB, o incluso potencialmente GB de y tirar de Windows en un frenesí latigazos, si no eliminar totalmente fuera del archivo de paginación y matar a su memoria del sistema en conjunto. Oops.

Entonces, con un poco más de iluminación, establecí el siguiente 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); 
} 

Esto funciona, incluso, y no sufre el problema de memoria paralizante de la última solución. Sin embargo, todavía es lento, especialmente en hardware antiguo, ya que graba datos (posiblemente de GB) en el disco.

La pregunta es: ¿hay una mejor manera de lograr lo mismo? ¿Hay alguna manera de decirle a Windows que cree un archivo de tamaño x y simplemente asigne el espacio en el sistema de archivos en lugar de escribir una tonelada de datos? No me importa inicializar los datos en el archivo (el protocolo que estoy usando - bittorrent - proporciona hashes para los archivos que envía, de ahí el peor caso para los datos aleatorios no inicializados es que obtengo una coincidencia afortunada y parte del archivo) es correcto).

Respuesta

23

FileStream.SetLength es el que desea. La sintaxis:

public override void SetLength(
    long value 
) 
+1

sí, eso es más fácil que mi solución :-) – Mark

5

Si usted tiene que crear el archivo, creo que es probable que pueda hacer algo como esto:

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

Dónde length_to_write sería el tamaño en bytes del archivo para escribir. No estoy seguro de tener la sintaxis C# correcta (no en una computadora para probar), pero he hecho cosas similares en C++ en el pasado y funcionó.

+0

Casi funciona. Tienes que buscar uno menos y luego escribir un byte; de ​​lo contrario, terminas con un archivo 0B. Aún muy útil, gracias! Corrija la sintaxis también. Si desea editar, la línea adicional que necesita es OutFile.WriteByte (0); –

+0

corregido por comentario anterior – Mark

1

Lamentablemente, no se puede hacer esto simplemente buscando hasta el final. Eso establecerá la longitud del archivo en algo enorme, pero puede que no asigne bloques de discos para el almacenamiento. Entonces, cuando vaya a escribir el archivo, aún fallará.

Cuestiones relacionadas