ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

低水準 I/O によるテキスト データ ファイルのインポート

概要

"低水準ファイル I/O 関数" では、ファイルの読み取りとファイルへのデータの書き込みを最大限に制御できます。ただし、importdata などの使いやすい "高水準関数" に比べ、これらの関数ではさらに詳細なファイル情報を指定する必要があります。テキスト ファイルの読み取りに使用する高水準関数の詳細は、「テキスト ファイルのインポート」を参照してください。

高水準関数でデータをインポートできない場合は、以下のいずれかを使用してください。

詳細は、以下の節を参照してください。

    メモ:   低水準ファイル I/O 関数は、ANSI® 標準 C ライブラリの関数を基に構成されています。ただし、MATLAB® にはそれらの関数の "ベクトル化" バージョンが含まれており、最小限の制御ループを使用して配列内のデータの読み取りと書き込みが行われます。

フォーマット済みパターン データの読み取り

importdatatextscan では読み取れないテキスト ファイルをインポートするには、fscanf の使用を検討してください。関数 fscanf ではファイルの形式を記述する必要がありますが、この形式の記述には多くのオプションがあります。

たとえば、下に示すようにテキスト ファイル mymeas.dat を作成します。mymeas.dat のデータには、一連の時刻、日付、および測定値が繰り返されています。ヘッダーのテキストには測定値のセットの数 N が含まれています。

Measurement Data
N=3

12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
9.15  0.35  7.57  NaN
7.92  8.49  7.43  7.06
9.59  9.33  3.92  0.31
09:10:02
23-Aug-1990
2.76  6.94  4.38  1.86
0.46  3.17  NaN   4.89
0.97  9.50  7.65  4.45
8.23  0.34  7.95  6.46
15:03:40
15-Apr-2003
7.09  6.55  9.59  7.51
7.54  1.62  3.40  2.55
NaN   1.19  5.85  5.05
6.79  4.98  2.23  6.99

ファイルを開く

あらゆる低水準 I/O 関数で行うように、読み取りの前に fopen でファイルを開き、ファイル識別子を取得します。既定では、'r' のアクセス許可で、fopen によってファイルが読み取りアクセス用に開きます。

ファイルの処理が終了したら、fclose(fid) を使用してこれを閉じます。

データの記述

文字列の '%s'、整数の '%d'、浮動小数点数の '%f' など、書式指定子によってファイルのデータを記述します (指定子の一覧は、fscanf のリファレンス ページを参照してください)。

ファイル内のリテラル文字をスキップするには、形式の記述にその文字を含めます。データ フィールドをスキップするには、指定子でアスタリスク ('*') を使用します。

たとえば、mymeas.dat のヘッダー行について考えます。

Measurement Data   % skip 2 strings, go to next line:  %*s %*s\n
N=3                % ignore 'N=', read integer:  N=%d\n
                   % go to next line:  \n
12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
...

ヘッダーを読み取って N に 1 つの値を返すには、次のようにします。

N = fscanf(fid, '%*s %*s\nN=%d\n\n', 1);

読み取る値の数の指定

既定の設定により、fscanf では記述がデータに一致しなくなるまで、またはファイル終端に到達するまで、形式の記述が繰り返し適用されます。

オプションとして、読み取る値の数を指定して、fscanf によりファイル全体が読み取られないようにします。たとえば、mymeas.dat では測定値の各セットに一定数の行と列が含まれています。

measrows = 4;
meascols = 4;
meas  = fscanf(fid, '%f', [measrows, meascols])';

ワークスペースにおける変数の作成

MATLAB ワークスペースで mymeas.dat を保管する方法はいくつかあります。ここでは、値を構造体に読み取ります。構造体の各要素には次の 3 つのフィールド mtimemdate および meas があります。

    メモ:   fscanf では、列順で配列に数値が埋められます。出力配列がファイルの数値データの配置と一致するようにするには、配列を転置してください。

filename = 'mymeas.dat';
measrows = 4;
meascols = 4;

% open the file
fid = fopen(filename);

% read the file headers, find N (one value)
N = fscanf(fid, '%*s %*s\nN=%d\n\n', 1);

% read each set of measurements
for n = 1:N
    mystruct(n).mtime = fscanf(fid, '%s', 1);
    mystruct(n).mdate = fscanf(fid, '%s', 1);

    % fscanf fills the array in column order,
    % so transpose the results
    mystruct(n).meas  = ...
      fscanf(fid, '%f', [measrows, meascols])';
end

% close the file
fclose(fid);

行単位データの読み取り

MATLAB には、ファイルから行を読み取って文字列ベクトルに格納する、次の 2 つの関数 fgetlfgets が用意されています。関数 fgets では改行文字が出力文字列にコピーされますが、fgetl ではコピーされません。

以下の例では、fgetl を使用してファイル全体を 1 行ずつ読み取ります。関数 litcount により、入力リテラル文字列 (literal) が各行に含まれるかどうかが判定されます。含まれる場合は、そのリテラル文字列が行に含まれる数に続き、その行全体が表示されます。

function y = litcount(filename, literal)
% Search for number of string matches per line.  

fid = fopen(filename);
y = 0;
tline = fgetl(fid);
while ischar(tline)
   matches = strfind(tline, literal);
   num = length(matches);
   if num > 0
      y = y + num;
      fprintf(1,'%d:%s\n',num,tline);
   end
   tline = fgetl(fid);
end
fclose(fid);

badpoem という名前の入力データ ファイルを作成します。

Oranges and lemons,
Pineapples and tea.
Orangutans and monkeys,
Dragonflys or fleas.

文字列 'an' がこのファイルにいくつ含まれるかを調べるために、litcount を呼び出します。

litcount('badpoem','an')

以下が返されます。

2: Oranges and lemons,
1: Pineapples and tea.
3: Orangutans and monkeys,
ans =
     6

ファイル終端 (EOF) のテスト

データの一部を読み取る場合、feof を使用してファイル終端に達したかどうかを確認できます。feof は、ファイル ポインターがファイル終端にあるとき 1 の値を返します。それ以外の場合は 0 を返します。

    メモ:   空のファイルを開いても、ファイルの位置指定子がファイル終端に "移動することはありません"。読み取り操作および関数 fseek と関数 frewind は、ファイル位置指定子を移動します。

feof による EOF のテスト

textscanfscanf、または fread を使用してデータを部分に分けて読み取る場合は、feof を使用してファイル終端に達したかどうかを確認できます。

たとえば、ファイル mymeas.dat が次の形態を取り、測定値セットの数に関する情報がない場合を仮定します。mtimemdate、および meas のフィールドをもつ構造体にデータを読み取ります。

12:00:00
01-Jan-1977
4.21  6.55  6.78  6.55
9.15  0.35  7.57  NaN
7.92  8.49  7.43  7.06
9.59  9.33  3.92  0.31
09:10:02
23-Aug-1990
2.76  6.94  4.38  1.86
0.46  3.17  NaN   4.89
0.97  9.50  7.65  4.45
8.23  0.34  7.95  6.46

ファイルを読み取るには次のようにします。

filename = 'mymeas.dat';
measrows = 4;
meascols = 4;

% open the file
fid = fopen(filename);

% make sure the file is not empty
finfo = dir(filename);
fsize = finfo.bytes;

if fsize > 0 

    % read the file
    block = 1;
    while ~feof(fid)
        mystruct(block).mtime = fscanf(fid, '%s', 1);
        mystruct(block).mdate = fscanf(fid, '%s', 1);

        % fscanf fills the array in column order,
        % so transpose the results
        mystruct(block).meas  = ...
          fscanf(fid, '%f', [measrows, meascols])';

        block = block + 1;
    end

end

% close the file
fclose(fid);

fgetl と fgets による EOF のテスト

制御ループで fgetl または fgets を使用する場合は、feof がファイル終端をテストする最良の方法であるとは限りません。代わりに、fgetl または fgets によって返される値が文字列であるかどうかを確認する方法を検討してください。

たとえば、「行単位データの読み取り」で説明した関数 litcount には、次の while ループと fgetl の呼び出しが含まれています。

y = 0;
tline = fgetl(fid);
while ischar(tline)
   matches = strfind(tline, literal);
   num = length(matches);
   if num > 0
      y = y + num;
      fprintf(1,'%d:%s\n',num,tline);
   end
   tline = fgetl(fid);
end

この方法は、以下の 2 つの理由で ~feof(fid) のテストよりもロバスト性が高くなります。

  • fgetl または fgets でデータが見つかった場合は、文字列が返されます。見つからない場合は数字 (-1) が返されます。

  • 読み取り操作が終わるごとに、fgetl および fgets ではファイル内の次の文字がファイル終端マーカーかどうかが確認されます。したがって、これらの関数では、-1 の値が "返される前に" ファイル終端指定子が設定される場合があります。たとえば、次に示す 3 行のテキスト ファイルについて考えます。最初の 2 行はどちらも改行文字で終了し、第 3 行にはファイル終端マーカーのみが含まれています。

    123
    456
    

    fgetl を 3 回続けて呼び出すと、次の結果が得られます。

    t1 = fgetl(fid);    % t1 = '123', feof(fid) = false
    t2 = fgetl(fid);    % t2 = '456', feof(fid) = true
    t3 = fgetl(fid);    % t3 = -1,    feof(fid) = true
    

    この動作は、関連する C 言語関数の ANSI 仕様には準拠していません。

異なった文字エンコードのファイルを開く

"エンコード スキーム" では、日本語や欧州の言語など、特定の文字体系で必要とされる文字がサポートされています。一般的なエンコード スキームには US-ASCII や UTF-8 などがあります。

エンコード スキームを指定しない場合、fopen でファイルが開かれるとシステムの既定のエンコードを使用して処理が行われます。既定の設定が何かを判断するには、ファイルを開き、次の構文で fopen を再度呼び出します。

[filename, permission, machineformat, encoding] = fopen(fid);

ファイルを開く際にエンコードを指定すると、そのスキームは次の関数 fscanffprintffgetlfgetsfread および fwrite で適用されます。

サポートされているエンコード スキームの一覧と、エンコードを指定する構文は、関数 fopen のリファレンス ページを参照してください。

この情報は役に立ちましたか?