Обработка ввода-вывода большого файла

Предпосылки к Использованию 64-битного ввода-вывода

MATLAB® поддерживает использование 64-битных операций файлового ввода-вывода в ваших программах файла MEX. Можно читать и записать данные к файлам, которые составили и больше, чем 2 Гбайт (2 31-1 байт) в размере. Некоторые операционные системы или компиляторы не делают файлов поддержки, больше, чем 2 Гбайт. Следующие темы описывают, как использовать 64-битный файловый ввод-вывод в ваших файлах MEX.

Заголовочный файл

Заголовочный файл io64.h задает многие типы и функции, требуемые для 64-битного файлового ввода-вывода. Оператор, чтобы включать этот файл должен быть первым оператором #include в вашем исходном файле и должен также предшествовать, любой системный заголовок включают операторы:

#include "io64.h"
#include "mex.h"

Описания типа

Чтобы объявить переменные, используемые в 64-битном файловом вводе-выводе, используйте следующие типы.

Тип MEX

Описание

POSIX

fpos_T

Объявляет 64-битный тип int для setFilePos() и getFilePos(). Заданный в io64.h h.

fpos_t

int64_T, uint64_T

Объявляет 64-битное целое число со знаком и типы беззнаковых целых чисел. Заданный в tmwtypes.h h.

long, long

structStat

Объявляет, что структура содержит размер файла. Заданный в io64.h h.

struct stat

FMT64

Используемый в mexPrintf, чтобы задать длину в спецификаторе формата, таком как %d. Смотрите пример в разделе Printing Formatted Messages. FMT64 задан в tmwtypes.h h.

%lld

LL, LLU

Суффиксы для литерального int постоянные 64-битные значения (C Стандартный ISO®/IEC 9899:1999 (E) Раздел 6.4.4.1). Используемый только в системах UNIX®.

LL, LLU

Функции

Используйте следующие функции для 64-битного файлового ввода-вывода. Все заданы в заголовочном файле io64.h h.

Функция

Описание

POSIX

fileno()

Получает дескриптор файла от указателя файла

fileno()

fopen

Открывает файл и получает указатель файла

fopen

getFileFstat()

Получает размер файла данной подсказки файла

fstat()

getFilePos()

Получает положение файла для следующего ввода-вывода

fgetpos()

getFileStat()

Получает размер файла данного имени файла

stat()

setFilePos()

Устанавливает положение файла для следующего ввода-вывода

fsetpos()

Определение постоянных литеральных значений

Чтобы присвоить подписанные и 64-битные целочисленные литеральные значения без знака, используйте определения типа int64_T и uint64_T.

В системах UNIX, чтобы присвоить литеральное значение целочисленной переменной, где значение, которое будет присвоено, больше, чем подписанный 2 31-1, необходимо снабдить суффиксом значение LL. Если значение больше, чем 2 32-1, без знака, то используйте LLU в качестве суффикса. Эти суффиксы не допустимы в системах Microsoft® Windows®.

Примечание

LL и суффиксы LLU не требуются для hardcoded (литерал) значения меньше, чем 2 G (2 31-1), даже если они присвоены 64-битному типу int.

Следующий пример объявляет 64-битную целочисленную переменную, инициализированную с большим литеральным значением int и две 64-битных целочисленных переменные:

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, 
                  const mxArray *prhs[])
{
#if defined(_MSC_VER) || defined(__BORLANDC__)     /* Windows */
   int64_T large_offset_example = 9000222000;
#else                                              /* UNIX    */
   int64_T large_offset_example = 9000222000LL;
#endif

int64_T offset   = 0;
int64_T position = 0;

Открытие файла

Чтобы открыть файл для чтения или записи, используйте функцию fopen C/C++, как вы обычно были бы. Пока вы включали io64.h в начале своей программы, fopen работает правильно на большие файлы. Никакие изменения вообще не требуются для fread, fwrite, fprintf, fscanf и fclose.

Следующие операторы открывают существующий файл для чтения и обновления в режиме двоичного счета.

fp = fopen(filename, "r+b");
if (NULL == fp)
   {
   /* File does not exist. Create new file for writing 
    * in binary mode.
    */
   fp = fopen(filename, "wb");
   if (NULL == fp)
      {
      sprintf(str, "Failed to open/create test file '%s'",
        filename);
      mexErrMsgIdAndTxt( "MyToolbox:myfnc:fileCreateError",
        str);
      return;
      }
   else
      {
      mexPrintf("New test file '%s' created\n",filename);
      }
   }
else mexPrintf("Existing test file '%s' opened\n",filename);

Печать форматированных сообщений

Вы не можете распечатать 64-битные целые числа с помощью спецификатора преобразования %d. Вместо этого используйте FMT64, чтобы задать соответствующий формат для вашей платформы. FMT64 задан в заголовочном файле tmwtypes.h h. Следующий пример показывает, как распечатать сообщение, показывающее размер большого файла:

int64_T large_offset_example = 9000222000LL;

mexPrintf("Example large file size: %" FMT64 "d bytes.\n",
           large_offset_example);

Заменяя fseek и ftell с 64-битными Функциями

ANSI® C fseek и функции ftell не являются 64-битным файловым вводом-выводом, способным на большинстве платформ. Функции setFilePos и getFilePos, однако, заданы как соответствующий POSIX® fsetpos и fgetpos (или fsetpos64 и fgetpos64) как требуется вашей платформой/ОС. Эти функции являются 64-битным файловым вводом-выводом, способным на всех платформах.

Следующий пример показывает, как использовать setFilePos вместо fseek и getFilePos вместо ftell. Пример использует getFileFstat, чтобы найти размер файла. Это затем использует setFilePos, чтобы стремиться в конец файла подготовиться к добавлению данных в конце файла.

Примечание

Несмотря на то, что параметр offset к setFilePos и getFilePos является действительно указателем на 64-битное целое число со знаком, int64_T, это должно быть брошено к fpos_T*. Тип fpos_T задан в io64.h как соответствующий fpos64_t или fpos_t, как требуется вашей платформой ОС.

getFileFstat(fileno(fp), &statbuf);
fileSize = statbuf.st_size;
offset = fileSize;

setFilePos(fp, (fpos_T*) &offset);
getFilePos(fp, (fpos_T*) &position );

В отличие от fseek, setFilePos поддерживает только абсолютный поиск относительно начала файла. Если вы хотите сделать, родственник ищет, сначала вызывает getFileFstat, чтобы получить размер файла. Затем преобразуйте относительное смещение в абсолютное смещение, которое можно передать setFilePos.

Определение размера открытого файла

Получить размер открытого файла:

  • Обновите запись размера файла, сохраненного в памяти с помощью getFilePos и setFilePos.

  • Получите размер файла с помощью getFileFstat.

Обновление записи размера файла

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

Чтобы обновить запись размера файла, ищите на любое смещение в файле с помощью setFilePos. Если вы не хотите менять положение указателя файла, можно искать на текущее положение в файле. Этот пример получает текущее смещение из запуска файла. Это затем стремится на текущее положение обновить размер файла, не перемещая указатель файла.

getFilePos( fp, (fpos_T*) &position);
setFilePos( fp, (fpos_T*) &position);

Получение размера файла

Функция getFileFstat берет входной параметр дескриптора файла. Используйте функцию fileno, чтобы получить указатель файла открытого файла. getFileFstat возвращает размер того файла в байтах в поле st_size структуры structStat.

structStat statbuf;
int64_T fileSize = 0;

if (0 == getFileFstat(fileno(fp), &statbuf))
   {
   fileSize = statbuf.st_size;
   mexPrintf("File size is %" FMT64 "d bytes\n", fileSize);
   }

Определение размера закрытого файла

Функция getFileStat берет имя файла закрытого файла как входной параметр. getFileStat возвращает размер файла в байтах в поле st_size структуры structStat.

structStat statbuf;
int64_T fileSize = 0;

if (0 == getFileStat(filename, &statbuf))
   {
   fileSize = statbuf.st_size;
   mexPrintf("File size is %" FMT64 "d bytes\n", fileSize);
   }
Была ли эта тема полезной?