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 |
|---|---|---|
|
|
|
| 64 ビット符号付きおよび符号なし整数型を宣言します。 |
|
| ファイルのサイズを保持する構造体を宣言します。 |
|
|
|
|
| リテラル |
|
関数
64 ビット ファイル I/O では次の関数が使用されます。これらはすべてヘッダー ファイル io64.h で定義されます。
関数 | 説明 | POSIX |
|---|---|---|
| ファイル ポインターからファイル記述子を取得します。 |
|
| ファイルを開き、ファイル ポインターを取得します。 |
|
| 指定されたファイル ポインターのファイル サイズを取得します。 |
|
| 次の I/O のファイルの位置を取得します。 |
|
| 指定されたファイル名のファイル サイズを取得します。 |
|
| 次の I/O のファイルの位置を設定します。 |
|
定数リテラル値の指定
符号付きおよび符号なし 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 および getFilePos の offset パラメーターは実際には符号付き 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);
}