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

Необходимые условия к использованию 64-Bit ввода-вывода

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

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

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

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

Объявления типов

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

Тип MEX

Описание

POSIX

fpos_T

Объявляет 64-разрядную int тип для setFilePos() и getFilePos(). Определено в io64.h.

fpos_t

int64_T, uint64_T

Объявляет 64-разрядные подписанные и неподписанные целые типы. Определено в tmwtypes.h.

long, long

structStat

Объявляет структуру для хранения размера файла. Определено в io64.h.

struct stat

FMT64

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

%lld

LL, LLU

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

LL, LLU

Функции

Используйте следующие функции для 64-разрядных операций ввода-вывода файлов. Все они определены в заголовочном файле io64.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 как суффикс. Эти суффиксы не действительны в корпорации Майкрософт® Windows® систем.

Примечание

The LL и LLU суффиксы не требуются для значений с жестким кодированием (литерал) менее 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;

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

Чтобы открыть файл для чтения или записи, используйте C/C + +fopen функционировать так, как обычно. Пока вы включили 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. В следующем примере показано, как напечатать сообщение с размером большого файла:

int64_T large_offset_example = 9000222000LL;

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

Замена fseek и ftell с 64-Bit функциями

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*. The 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);

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

The 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);
   }

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

The 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);
   }