MATLAB-Sample 【基礎】ファイル入出力

簡単に使えそうな、データのファイル入出力。

# 行列データをCSVファイルに保存

`csvwrite`関数を使って、行列データをファイルへ出力してみる。
出力されるファイルは区切り文字がカンマになっている。

```matlab
> A = [ 1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ; 13 14 15 16 ; 17 18 19 20 ];
> %行列Aを、ファイルパス'D:\MatrixA.csv'に出力する。
> %ファイルパスは、各自の環境で出力可能なファイルパスを指定すること。
> %尚、windows環境の場合、ファイルパスのセパレータ「\」はエスケープする必要がないみたい。
> csvwrite('D:\MatrixA.csv', A);
```

これで第1引数に指定したファイルパスに出力されているはず。
Explorer等から直接テキストエディタで確認するのもいいけれど、MATLABのインタラクティブシェル？からファイルの中身を閲覧できるコマンド`type`があるので、それを使って中身を見てみる。

```matlab
> type 'D:\MatrixA.csv'
1,2,3,4
5,6,7,8
9,10,11,12
13,14,15,16
17,18,19,20
```


# CSVファイルから行列データを読み込む

`csvread`関数を使って、CSVファイルを読み込みで行列データを生成する。

**！！注意！！
`csvread`関数を使う場合は、数値データのみで構成されているCSVファイルを使うこと。
ヘッダ等の文字列データが混在する場合は、`csvread`を使うより、後述の`textscan`関数を使ったほうが適切。**

今回は準備として、前項「行列データをCSVファイルに保存」を先に実施しておき、そこで生成したMatrixA.csvを使う。
というわけで、MatrixA.csvから読み込んだデータを、行列Bに格納するには次のように記述する。

```matlab
> %第1引数に読み込むファイルのパスを指定する。
> %読み込んだデータは、返り値として行列Bに格納される。
> B = csvread('D:\MatrixA.csv');
> B

B =

  1  2  3  4
  5  6  7  8
  9 10 11 12
 13 14 15 16
 17 18 19 20

```

また、`csvread`関数は、CSVファイルから読み込む際の行と列のOffsetを指定できる。
こんな感じ。

```matlab
> %第2引数に行のオフセット、第3引数に列のオフセットを指定する。
> %以下の場合、3行目からと2列目からの要素を3×3行列として読み込む。
> B = csvread('D:\MatrixA.csv', 2, 1);
> B

B =

 10 11 12
 14 15 16
 18 19 20

```

Offsetだけでは、範囲の末尾の指定が行列の最終行最終列までの固定になってしまう。
途中の行、途中の列までの領域を指定するには、第4引数に領域情報を指定することで可能となる。

```matlab
> %第4引数に領域情報を指定する。
> %以下の場合、領域の左上を3行2列目、右下を4行3列目として読み込む。
> B = csvread('D:\MatrixA.csv', 2, 1, [2 1 3 2]);
> B

B =

 10 11
 14 15

```



# フォーマット付きでファイルからデータを読み込む

`textscan`関数を使う。

この関数は`csvread`関数と異なり、読み込みたいファイルのオープン（`fopen`関数）とクローズ（`fclose`関数）が必要。
読み込みは、`textscan`関数で一気にセル配列（セル配列についても別記事を作らねば…）として取得できる。

一応よく使いそうなパターンでの引数を説明。上から下へ、第1引数から。

```matlab
data = textscan(fileId, format[[, keyword, value] ...]);
```

| fileId  | ファイル記述子 |`fopen`関数でオープンしてから渡す。|
| format  | フォーマット文字列|「変換指定子」の羅列。該当する位置のデータを指定したデータ型で取得する。文字列、数値等、様々な変換指定子がある。|
| keyword | キーワード文字列 |オプショナル引数。挙動を変更する。フィールドのセパレータ等を指定できる。|
| value   | キーワードの値 |オプショナル引数。キーワードに対する挙動の指定を行う。|

変換識別子とキーワード文字列に関しては情報が多すぎるので詳細はここでは触れない。（例として使うやつだけは説明するけれども。）
尚、`textscan`関数はファイルからの読み込みだけでなく、単なる文字列の解析にも使えるらしい。
これらについての詳細はヘルプを参照のこと。

では実例を。次のようなデータが記述されているCSVファイルを適当なパスに用意しておく。ここでは、「'D:\MatrixA_with_Text.csv'」ということにしておこう。

```matlab
> type 'D:\MatrixA_with_Text.csv';
line,field1,field2,field3,field4
line1,1.2,2.3,3.4,4.5
line2,5.6,6.7,7.8,8.9
line3,9.0,10.1,11.2,12.3
```

このファイルの2行目以降かつ2列目以降のデータを取得したい場合、`textscan`関数では次のように指定する。

1. 1行目を「ヘッダ行」とみなして読み飛ばす。その為、キーワード＝`'headerLines'`、キーワードの値＝`1`として指定する。
2. 1列目を文字列とみなした上で読み飛ばし、2列目以降は数値として読み込む。フォーマット文字列は`'%*s%n%n%n\n'`のようになる。
3. CSVのフィールドセパレータを「,」として指定する。その為、キーワード＝`'delimiter'`、キーワードの値＝`','`として指定する。

ここで指定するフォーマット文字列の変換指定子を分解するは、次のようになっている。

|  記号  |説明|
|:-----------|:------------|
|  `%`  |変換指定子の開始。`%`の後ろに続く文字や数字が変換指定子の挙動を決定する。|
|  `*`  |該当位置のデータを読み飛ばす。例えば上記の例だと、1列目の文字列データを読み飛ばすことになる。`%*n`ならば、該当位置に相当する数値データを読み飛ばすことになる。|
|  `s`  |`%s`で該当位置のテキストを文字列データとして読み込む。|
|  `n`  |`%n`で該当位置のテキストを数値データとして読み込む。|

では実際のコードを。

```matlab
> % まずは対象のファイルをオープンする。
> fileId = fopen('D:\MatrixA_with_Text.csv', 'r');
> % オープンしたファイルIDを指定してファイルの内容を読み込む。
> data = textscan(fileId, '%*s%n%n%n', 'delimiter', ',', 'headerLines', 1 );
> % 開いたファイルIDは必ずクローズする。
> fclose(fileId);
> % 取得したデータを表示してみる。
> data

data = 

    [3x1 double]    [3x1 double]    [3x1 double]    [3x1 double]

> % ↑セル配列の表現。なので、次のように中括弧を使ってアクセスする。
> data{1};
> % ・・・これだと表示してくれないようなので一度変数に格納する。
> % というわけで1列目
> column1 = data{1};
> column1

column1 =

    1.2000
    5.6000
    9.0000

> % 2列目（3列目以降は省略。中括弧の中の数字を変えていけばよい。）
> column2 = data{2};
> column2

column2 =

    2.3000
    6.7000
   10.1000

> 
```