exponenta event banner

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

Предпосылки для использования 64-Bit ввода-вывода

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.

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-разрядные значения (C стандарт ISO ®/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 в качестве суффикса. Эти суффиксы недопустимы в системах Microsoft ® Windows ®.

Примечание

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 ® Cfseek и 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);
   }