Как предварительно выделить место для файла в C / C ++ в Windows? - PullRequest
15 голосов
/ 01 ноября 2011

Я добавляю некоторые функциональные возможности в существующую базу кода, которая использует чистые функции C (fopen, fwrite, fclose) для записи данных в файл. К сожалению, я не могу изменить реальный механизм файлового ввода-вывода, но мне нужно заранее выделить место для файла, чтобы избежать фрагментации (что убивает нашу производительность во время чтения). Есть ли лучший способ сделать это, чем записать в файл нули или случайные данные? Я знаю окончательный размер файла, когда открываю его.

Я знаю, что могу использовать Fallocate в Linux, но я не знаю, каков эквивалент Windows.

Спасибо!

Ответы [ 5 ]

17 голосов
/ 01 ноября 2011

Программно, в Windows вы должны использовать функции Win32 API для этого:

SetFilePointerEx() followed by SetEndOfFile()

Вы можете использовать эти функции, чтобы предварительно выделить кластеры для файла и избежать фрагментации. Это работает намного эффективнее, чем предварительная запись данных в файл. Сделайте это до того, как сделать fopen().

Если вы хотите вообще избежать Win32 API, вы можете сделать это непрограммически, используя функцию system (), чтобы выполнить следующую команду:

fsutil file createnew filename filesize
6 голосов
/ 01 ноября 2011

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

Я бы рекомендовал вместо этого просто писать 0. Вы также можете использовать SetFilePointerEx и SetEndOfFile, чтобы расширить файл, но для этого по-прежнему требуется записать нули на диск (если файл не разрежен, но это побеждает точку резервирования дискового пространства). См. Почему моя однобайтовая запись занимает вечность? для получения дополнительной информации об этом.

3 голосов
/ 01 ноября 2011

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

if (  INVALID_HANDLE_VALUE != (handle=CreateFile(fileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL) )) {                                               
        // preallocate 2Gb disk file                
        LARGE_INTEGER size;
        size.QuadPart=2048 * 0x10000;
        ::SetFilePointerEx(handle,size,0,FILE_BEGIN);
        ::SetEndOfFile(handle);
        ::SetFilePointer(handle,0,0,FILE_BEGIN);
}
1 голос
/ 02 ноября 2011

Вы можете использовать функцию _chsize () .

0 голосов
/ 01 ноября 2011

Проверьте этот пример на Code Project. Очень просто установить размер файла при первоначальном создании.

http://www.codeproject.com/Questions/172979/How-to-create-a-fixed-size-file.aspx

FILE *fp = fopen("C:\\myimage.jpg","ab");

fseek(fp,0,SEEK_END);
long size = ftell(fp);

char *buffer = (char*)calloc(500*1024-size,1);
fwrite(buffer,500*1024-size,1,fp);

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