Pregunta

Estoy creando una aplicación de descarga y deseo preallocar espacio en el Drive Drive 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, elimine algunos archivos e intente nuevamente. " Entonces, en ese sentido, escribí esto.

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

Funciona, al menos hasta que descargas un archivo que tiene varios cientos de MB, o potencialmente incluso GB, y lanzas a Windows a un frenesí, si no borras por completo el archivo de paginación y matas la memoria de tu sistema por completo.Ups.

Entonces, con un poco más de iluminación, comencé con 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 bien, y no sufre el problema de memoria paralizante de la última solución.Sin embargo, sigue siendo lento, especialmente en hardware antiguo, ya que escribe datos (potencialmente equivalentes a GB) en el disco.

La pregunta es esta:¿Existe 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 en absoluto inicializar los datos en el archivo (el protocolo que estoy usando, bittorrent, proporciona hashes para los archivos que envía, por lo tanto, el peor caso para datos aleatorios no inicializados es que tenga una coincidencia afortunada y parte del archivo es correcto).

¿Fue útil?

Solución

FileStream.SetLongitud es el que quieres.La sintaxis:

public override void SetLength(
    long value
)

Otros consejos

Si tienes que crear el archivo, creo que probablemente puedas hacer algo como esto:

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

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

Desafortunadamente, no puedes lograr esto simplemente buscando hasta el final.Eso establecerá la longitud del archivo en algo enorme, pero es posible que en realidad no asigne bloques de disco para almacenamiento.Entonces, cuando vayas a escribir el archivo, seguirá fallando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top