Предварительно выделить файловое пространство в C #? - PullRequest
15 голосов
/ 19 сентября 2008

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

// 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 - предоставляет хэши для отправляемых файлов, поэтому наихудший случай для случайных неинициализированных данных - случайное совпадение и часть файла. правильно).

Ответы [ 3 ]

25 голосов
/ 19 сентября 2008

FileStream.SetLength - это то, что вам нужно. Синтаксис:

public override void SetLength(
    long value
)
5 голосов
/ 19 сентября 2008

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

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

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

2 голосов
/ 19 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...