Создание большого файла в Windows

Мне нужно создать большие относительно большие (1-8 ГБ) файлы. Каков самый быстрый способ сделать это в Windows с помощью C или C++? Мне нужно создавать их на лету, и скорость действительно проблема. Файл будет использоваться для эмуляции хранилища, т.е. доступ к нему будет случайным образом с разными смещениями, и мне нужно, чтобы все хранилище было предварительно выделено, но не инициализировано, в настоящее время мы записываем все хранилище с фиктивными данными, и это занимает слишком много времени.

Спасибо.


person Ilya    schedule 18.01.2009    source источник


Ответы (6)


Используйте Win32 API, CreateFile, SetFilePointerEx, SetEndOfFile и CloseHandle. В том же порядке.

Хитрость заключается в функции SetFilePointerEx. Из MSDN:

Обратите внимание, что установка указателя файла за конец файла не является ошибкой. Размер файла не увеличивается, пока вы не вызовете функцию SetEndOfFile, WriteFile или WriteFileEx.

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

person Brian R. Bondy    schedule 18.01.2009
comment
Это будет работать быстро только на NTFS и exFAT, а не на FAT32, FAT16.. Это потому, что эти файловые системы имеют инициализированный размер - person Dominik Weber; 25.08.2010
comment
SetEndOfFile() может привести к серьезным задержкам при записи в файл. Если вы записываете в середину файла, Windows обнулит все блоки, в которые еще не были записаны данные, вплоть до места записи. См. blogs.msdn.com/b/oldnewthing/archive. /2011/09/22/10215053.aspx (И я могу лично подтвердить это. Я сам наблюдал эффект, когда писал тестовое приложение ввода-вывода.) - person Paul Groke; 14.02.2014
comment
Ваше решение инициализируется нулями, посмотрите здесь. - person ST3; 04.08.2014

Просмотрите файлы с отображением памяти.

Они очень соответствуют описанному вами варианту использования, высокой производительности и произвольному доступу.

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

person Laserallan    schedule 18.01.2009
comment
Использование отображаемых в память файлов также приводит к дополнительным сложностям: сообщения об ошибках сообщаются через структурированные исключения, а не возвращаемые значения функции, и вы не сможете отобразить весь файл размером 8 ГБ в память в 32-разрядной версии Windows, поскольку у вас есть только 2 ГБ виртуальной памяти. адресное пространство (или 3 ГБ, если повезет). - person bk1e; 19.01.2009
comment
Вам определенно нужно будет использовать окно (или несколько, если вы используете много частей файла независимо) для сопоставления того, что имеет отношение к памяти. В любом случае, если вы используете стандартный файловый ввод-вывод, у вас не будет доступа ко всему файлу. Это просто сделано с использованием fseeks, а не изменением того, что отображается в памяти. - person Laserallan; 22.01.2009

Что ж, это решение неплохое, но то, что вы ищете, это SetFileValidData

Как говорит MSDN:

Функция SetFileValidData позволяет избежать заполнения данных нулями при непоследовательной записи в файл.

Таким образом, всегда оставляйте данные на диске такими, какие они есть, SetFilePointerEx должен устанавливать все данные в нули, поэтому большое распределение занимает некоторое время.

person ST3    schedule 04.08.2014
comment
Обратите внимание, что SetFileValidData представляет собой огромную угрозу безопасности, поэтому вам нужен привилегированный процесс, чтобы иметь возможность использовать эту функцию. Решение, предложенное Laserallan (файлы с отображением памяти), гораздо предпочтительнее, если у вас достаточно адресного пространства. Создание сопоставления произвольного размера — это быстро и безопасно. - person Damon; 04.08.2014

Используйте команду «fsutil»:

E:\VirtualMachines>файл fsutil createnew Использование: файл fsutil createnew Например: файл fsutil createnew C:\testfile.txt 1000

Реагды

P.S. это для Windows: 2000/XP/7

person opal    schedule 23.06.2010

Если вы используете NTFS, то разреженные файлы путь:

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

Сжатие файлов в файловой системе NTFS является частичным решением проблемы. Все данные в файле, которые не записаны явно, явно обнуляются. Сжатие файлов сжимает эти диапазоны нулей. Однако недостатком сжатия файлов является то, что время доступа может увеличиться из-за сжатия и распаковки данных.

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

person Stu Mackellar    schedule 18.01.2009
comment
Нет - ему нужно предварительно выделить экстенты. - person Dominik Weber; 25.08.2010

Я знаю, что ваш вопрос помечен как Windows, и Брайан Р. Бонди дал вам лучший ответ на ваш вопрос, если вы точно знаете, что вам не придется переносить свое приложение на другие платформы. Однако, если вам, возможно, придется перенести свое приложение на другие платформы, вы можете сделать что-то более похожее на то, что предложил Адриан Корниш в качестве ответа на вопрос «Как создать файл размера «x»?» можно найти по адресу Как создать файл размера x?.

FILE *fp=fopen("myfile", "w");
fseek(fp, 1024*1024, SEEK_SET);
fputc('\n', fp);
fclose(fp);

Конечно, есть дополнительная изюминка. В ответе, предложенном Адрианом Корнишем, используется функция fseek со следующей подписью.

int fseek ( FILE * stream, long int offset, int origin );

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

Заголовочный файл LargeFileSupport.h находится по адресу http://mosaik-aligner.googlecode.com/svn-history/r2/trunk/src/CommonSource/Utilities/LargeFileSupport.h предлагает решение этой проблемы.

Это позволит вам написать следующую функцию.

#include "LargeFileSupport.h"
/* Include other headers. */

bool createLargeFile(const char * filename, off_type size)
{
    FILE *fp = fopen(filename, "w");
    if (!fp)
    {
        return false;
    }
    fseek64(fp, size, SEEK_SET);
    fputc('\n', fp);
    fclose(fp);
}

Я подумал, что добавлю это на всякий случай, если информация будет вам полезна.

person Ben Key    schedule 04.08.2014