Как вы предварительно распределите пространство для файла в C/С++ в Windows?

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

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

Спасибо!

Ответы

Ответ 1

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

SetFilePointerEx() followed by SetEndOfFile()

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

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

fsutil file createnew filename filesize

Ответ 2

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

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

Ответ 3

Пример кода, обратите внимание, что это не обязательно быстрее, особенно в таких интеллектуальных файловых системах, как 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);
}

Ответ 4

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

Ответ 5

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

http://www.codeproject.com/info/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);