Main Content

MEX ファイルでの大規模なファイル I/O の処理

64 ビット I/O の使用の前提条件

MATLAB® は、MEX ファイル プログラム内での 64 ビット ファイル I/O の使用をサポートしています。サイズが 2 GB (2 31-1 バイト) 以下のファイルとそれより大きいファイルにデータの読み取りおよび書き込みを行うことができます。オペレーティング システムおよびコンパイラによっては、2 GB を超えるサイズのファイルをサポートしていない場合があります。以下のトピックでは、MEX ファイルで 64 ビット ファイル I/O を使用する方法について説明します。

ヘッダー ファイル

ヘッダー ファイル io64.h は 64 ビット ファイル I/O に必要な型と関数の多くを定義します。このファイルをインクルードするステートメントは、ソース ファイル内の "最初の" #include ステートメントでなければならず、またどのシステム ヘッダーのインクルード ステートメントよりも前になければなりません。

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

型の宣言

64 ビット ファイル I/O で使用される変数を宣言するために、以下の型を使用します。

MEX 型

説明

POSIX

fpos_T

setFilePos() および getFilePos() について 64 ビット int 型を宣言します。io64.h で定義されます。

fpos_t

int64_T, uint64_T

64 ビット符号付きおよび符号なし整数型を宣言します。tmwtypes.h で定義されます。

long, long

structStat

ファイルのサイズを保持する構造体を宣言します。io64.h で定義されます。

struct stat

FMT64

%d のような書式指定子内で長さを指定するために mexPrintf で使用されます。書式設定されたメッセージの出力の節の例を参照してください。FMT64tmwtypes.h で定義されます。

%lld

LL, LLU

リテラル int 定数 64 ビット値の接尾辞 (C 標準 ISO®/IEC 9899:1999(E) Section 6.4.4.1)。UNIX® システムでのみ使用されます。

LL, LLU

関数

64 ビット ファイル I/O では次の関数が使用されます。これらはすべてヘッダー ファイル io64.h で定義されます。

関数

説明

POSIX

fileno()

ファイル ポインターからファイル記述子を取得します。

fileno()

fopen()

ファイルを開き、ファイル ポインターを取得します。

fopen()

getFileFstat()

指定されたファイル ポインターのファイル サイズを取得します。

fstat()

getFilePos()

次の I/O のファイルの位置を取得します。

fgetpos()

getFileStat()

指定されたファイル名のファイル サイズを取得します。

stat()

setFilePos()

次の I/O のファイルの位置を設定します。

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 型に割り当てられている場合も含む)。

次の例では、大きいリテラル値 int で初期化された 64 ビット整数変数と 2 つの 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:myfcn:fileCreateError",
        str);
      return;
      }
   else
      {
      mexPrintf("New test file '%s' created\n",filename);
      }
   }
else mexPrintf("Existing test file '%s' opened\n",filename);

書式設定されたメッセージの出力

%d 変換指定子を使用して 64 ビット整数を出力することはできません。代わりに 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 ビット関数による置換

ANSI® C 関数 fseek および ftell は、ほとんどのプラットフォームで 64 ビット ファイル I/O に対応していません。しかし、関数 setFilePos および関数 getFilePos は、プラットフォームまたは OS の必要に応じて、対応する POSIX®fsetpos および fgetpos (または fsetpos64 および fgetpos64) として定義されます。これらの関数は、すべてのプラットフォームで 64 ビット ファイル I/O に対応しています。

この例は、fseek および ftell の代わりに setFilePos および getFilePos を使用する方法を示します。例では、getFileFstat を使用してファイルのサイズを求めます。そのうえで、setFilePos を使用してファイルの末尾を探索し、末尾へのデータ追加に備えます。

メモ

setFilePos および getFilePosoffset パラメーターは実際には符号付き 64 ビット整数 int64_T へのポインターですが、このパラメーターは fpos_T* にキャストしなければなりません。fpos_T 型は、プラットフォーム OS の必要に応じて、適切な fpos64_t または fpos_t として io64.h で定義されます。

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 は、structStat 構造体の st_size フィールドにそのファイルのサイズをバイト単位で返します。

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 は、structStat 構造体の st_size フィールドにファイルのサイズをバイト単位で返します。

structStat statbuf;
int64_T fileSize = 0;

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