Предварительное выделение файлового пространства в С#?

Я создаю загружающее приложение, и я хочу предварительно выделить место на жестком диске для файлов, прежде чем они будут загружены, поскольку они потенциально могут быть довольно большими, и никто не любит видеть: "Этот диск заполнен, удалите некоторые файлы и попробуй еще раз." Итак, в этом свете я написал это.

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

Он работает, по крайней мере, до тех пор, пока вы не загрузите файл размером несколько сотен МБ или, возможно, даже ГБ, и вы бросите Windows в изнурительное безумие, если не полностью уничтожить файл подкачки и полностью уничтожить свою системную память. К сожалению.

Итак, с немного более просветленным, я изложил со следующим алгоритмом.

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

Это работает, даже хорошо, и не страдает от проблемы с повреждением последнего решения. Тем не менее, он все еще медленный, особенно на устаревшем оборудовании, поскольку он записывает данные (потенциально опасные данные) на диск.

Вопрос заключается в следующем: есть ли лучший способ выполнить одно и то же? Есть ли способ сообщить Windows создать файл размера x и просто выделить пространство в файловой системе, а не записывать тонну данных. Мне вообще не нужна инициализация данных в файле (протокол, который я использую - bittorrent - предоставляет хэши для файлов, которые он отправляет, поэтому худший случай для случайных неинициализированных данных - я получаю удачное совпадение и часть файла правильно).

Ответы

Ответ 1

FileStream.SetLength - тот, который вы хотите. Синтаксис:

public override void SetLength(
    long value
)

Ответ 2

Если вам нужно создать файл, я думаю, что вы, вероятно, можете сделать что-то вроде этого:

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

Где length_to_write будет размером в байтах файла для записи. Я не уверен, что у меня правильный синтаксис С# (а не на компьютере для тестирования), но в прошлом я делал подобные вещи на С++ и работал.

Ответ 3

К сожалению, вы не можете этого сделать, просто добиваясь конца. Это установит длину файла на что-то огромное, но на самом деле не может выделять блоки диска для хранения. Поэтому, когда вы идете писать файл, он все равно будет терпеть неудачу.