Предварительное выделение файлового пространства в C#?
Вопрос
Я создаю приложение для загрузки, и я хочу предварительно рассказать комнату на жестком плане для файлов, прежде чем они на самом деле будут загружены, поскольку они потенциально могут быть довольно большими, и никто не любит видеть »этот диск заполнен, удалите несколько файлов и попробуйте еще раз. " Итак, в этом свете я написал это.
// 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 — предоставляет хэши для файлов, которые он отправляет, поэтому худший случай для случайных неинициализированных данных — это то, что я получаю счастливое совпадение и часть файла верно).
Решение
FileStream.SetLength это тот, который вам нужен.Синтаксис:
public override void SetLength(
long value
)
Другие советы
Если вам нужно создать файл, я думаю, вы можете сделать что-то вроде этого:
using (FileStream outFile = System.IO.File.Create(filename))
{
outFile.Seek(<length_to_write>-1, SeekOrigin.Begin);
OutFile.WriteByte(0);
}
Где length_to_write — это размер записываемого файла в байтах.Я не уверен, что у меня правильный синтаксис C# (не на компьютере для тестирования), но в прошлом я делал подобные вещи на C++, и это работало.
К сожалению, вы не сможете добиться этого, просто стремясь до конца.Это приведет к тому, что длина файла станет огромной, но фактически не сможет выделить дисковые блоки для хранения.Поэтому, когда вы приступите к записи файла, он все равно не удастся.