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:myfnc: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
は閉じているファイルのファイル名を入力引数として使用し、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); }