Talend入門 (2)　～ファイルI/O～

##全体の目的
Talendの超簡単なサンプルジョブを作成して，ETLジョブ開発に必要なスキルを習得することが目的です。

##対象者
ETL / EAI技術者

##環境
|使用環境|バージョン|
|:----:|:------------------|
|OS|Windows10|
|Talend|7.1.1|	

##サンプル一覧
以下の順番で習得していきます

|#|内容|
|:----:|:------------------|
|1|[はじめてのTalend](https://qiita.com/airkoda/items/a837d3c5d851d98d2612)|
|**2**|**[ファイルI/O（今回）](https://qiita.com/airkoda/items/1cd12c05c6136add7178)**|
|3|[データベースI/O](https://qiita.com/airkoda/items/bc807c920c3adebad837)|
|4|[tMap](https://qiita.com/airkoda/items/fa4a9c022b5d688698e0)|
|5|[イテレータ](https://qiita.com/airkoda/items/404d2d65eff535b2126c)|
|6|[メタデータ](https://qiita.com/airkoda/items/4b42cf2a86f34abb6c87)|
|7|[Context変数](https://qiita.com/airkoda/items/42d294fca40b81aa20fb)|
|8|[Global Map](https://qiita.com/airkoda/items/1aba0d36905c755deeae)|
|9|[tHashInput/tHashOutput](https://qiita.com/airkoda/items/d9347865190f0f3ab180)|
|10|[エラーハンドリング](https://qiita.com/airkoda/items/85e7c49a9bf6a21db6d5)|
|11|[ロギング](https://qiita.com/y-fujioka-yoshiharu/items/e0280f34cff2e3d00bda)|
|12|[子ジョブ（ジョブのネスト）](https://qiita.com/y-fujioka-yoshiharu/items/04ea4bd74ded382cf03c)|
|13-1|[設定ファイル読み込みオリジナル版](https://qiita.com/airaotaku/items/92f114795108f25e6d0f)|
|13-2|[設定ファイル読み込みコンポ版](https://qiita.com/airyama/items/83c2bf9b2d51a79c3714)|
|14|[tJava](https://qiita.com/airkoda/items/4d81d76c36b6fcbd4d89)|

[サンプルコード（Talendプロジェクトデータ）](https://github.com/kd2air/qiita)

##今回の目的
ファイル入出力について理解する。

##サンプルプログラム概要
csvを読み込みtsvを出力するプログラムを作ってみます。

##CSVファイル読み込み
まずは入力ソースとしてETLでよく使われるCSVファイルを読み込んでみましょう。

#### 入力ソース作成
in.csvというファイルを作成します。

- エンコードはシフトJIS
- 改行コードはLF

```csv:in.csv
id,name,gender
1,kouda,男
2,mori,男
3,kubo,男
4,shimizu,男
5,aya,女
```

#### CSV読み込み
リポジトリの[ジョブ]を右クリックし[ジョブの作成]を選択します。
![WS000021.png](https://qiita-image-store.s3.amazonaws.com/0/364565/416f0b33-8338-f2b6-6f41-257ffbc2c4dc.png)

[名前]に"fileio"と入力し[Finish]ボタンをクリックします。
![GS000015.png](https://qiita-image-store.s3.amazonaws.com/0/364565/5d008bb5-756b-dc2f-37ae-1bee1fd514a8.png)

csvファイル読み込みには[tFileInputDelimited]コンポーネントを使います。
[tFileInputDelimited]と読み込みデータ確認用に[tLogRow]を配置します。
![GS000017.png](https://qiita-image-store.s3.amazonaws.com/0/364565/6a824bb2-2fb0-1d04-0c58-420f5abb9b78.png)

[tFileInputDelimited]の[基本設定]を以下のように設定します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名    | C:/work/fileio/in.csv  | 読み込みファイルのパス|
| フィールド区切り  | , | 入力データに合わせてカンマを指定 |
| ヘッダー  | 1 | 1行目はヘッダとして扱う |
![GS000018.png](https://qiita-image-store.s3.amazonaws.com/0/364565/66f1eff7-77e5-e419-e9fc-7856aaf3e984.png)

[tFileInputDelimited]の[詳細設定]でエンコーディングを指定します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| エンコーディング    | CUSTOMでSJIS  | 入力ファイルのエンコーディングに合わせる|
![GS000019.png](https://qiita-image-store.s3.amazonaws.com/0/364565/650be798-2dc7-460f-4e9f-8c871e217445.png)

[tFileInputDelimited]の[基本設定]の[スキーマ編集]ボタンを押下しカラム定義画面を開きます。
![GS000021.png](https://qiita-image-store.s3.amazonaws.com/0/364565/182acbfd-02c6-88c9-fcb4-40ebc2f9b6ec.png)

カラム名とタイプを以下のように設定します。

| 列      | カラム |  タイプ |
|:-----------------|:------------------|:------------------|
| 1列目    | id  | int|
| 2列目    | name  | String|
| 3列目    | gender  | String|

![GS000033.png](https://qiita-image-store.s3.amazonaws.com/0/364565/c2ad76f0-766d-cf5a-c51a-0c6e432b5ce5.png)

[tLogRow]の[基本設定]にある[モード]をテーブルにします。
![GS000020.png](https://qiita-image-store.s3.amazonaws.com/0/364565/23395f91-ba4d-ab2d-9fc3-cdf69ff86ebf.png)

[tFileInputDelimited]と[tLogRow]をロウでつなぎます。

![GS000022.png](https://qiita-image-store.s3.amazonaws.com/0/364565/3ab53c3b-7b35-857b-6e92-4feca66303c5.png)

これで設定は完了ですので実行してみます。
in.csvが設定どおり読み込めたことを確認できます。
![GS000023.png](https://qiita-image-store.s3.amazonaws.com/0/364565/be19a66e-a626-6890-268e-bdcab9a98d7a.png)

#### ファイル出力の設定

今度は実際のファイルに出力してみます。
[tFileOutputDelimited]というファイル出力用のコンポーネントを配置します。
![GS000024.png](https://qiita-image-store.s3.amazonaws.com/0/364565/578e0184-6a51-33b6-46f1-afbb57be8466.png)

[tLogRow]とロウをつなぎ[tFileOutputDelimited]の[基本設定]を以下のように設定します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| ファイル名    | C:/work/fileio/out.tsv  | 出力ファイルのパス|
| フィールド区切り  | \t | 今回はタブ区切りで出力する |
| ヘッダーを含む  | チェック | ヘッダを出力する |
![GS000026.png](https://qiita-image-store.s3.amazonaws.com/0/364565/165a12bc-e5c8-aadf-8ae1-b37598e42bce.png)

[tFileOutputDelimited]の[詳細設定]でエンコーディングを指定します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| エンコーディング    | UTF-8  | 出力したエンコーディングを指定|
| CSVオプション    | チェック  | 囲み文字を設定する|
| ファイルが既に存在する場合はエラーが発生します | チェックなし | 毎回上書きにする|
![GS000047.png](https://qiita-image-store.s3.amazonaws.com/0/364565/30f7aa4a-61ab-175b-ba15-5f34662d1157.png)

これで準備は完了です。実行してみましょう。
タブ区切りのファイルが出力できます。

```csv:out.tsv
id	name	gender
"1"	"kouda"	"男"
"2"	"mori"	"男"
"3"	"kubo"	"男"
"4"	"shimizu"	"男"
"5"	"aya"	"女"
```

#### 入力ソースをジョブ内で定義（おまけ）
ちょっとした検証をしたい場合、入力ファイルを都度作るのは少々手間がかかります。
そんな時に便利な**独自定義の入力ソースをジョブ内で定義する方法**を紹介します。

[tFixedFlowInput]コンポーネントを配置します。
![GS000037.png](https://qiita-image-store.s3.amazonaws.com/0/364565/2c954dbc-bce3-8a2d-05e3-414d6a395b8e.png)

[tFixedFlowInput]の[基本設定]の[スキーマ編集]ボタンを押下しカラム定義画面を開きます。
カラム名とタイプを以下のように設定します。先ほどと違いが分かるようにカラム名を大文字にしています。

| 列      | カラム |  タイプ |
|:-----------------|:------------------|:------------------|
| 1列目    | ID  | int|
| 2列目    | NAME  | String|
| 3列目    | GENDER  | String|
![GS000035.png](https://qiita-image-store.s3.amazonaws.com/0/364565/332ceb84-d613-61e0-b702-bce6bbda3603.png)

[tFixedFlowInput]の[基本設定]のモード設定で[インラインコンテンツの使用]を選び以下設定します。

| 項目名              | 設定内容 |    説明  |
|:-----------------|:------------------|:------------------|
| フィールド区切り  | , | 入力データはcsv定義 |
| コンテンツ  | 上記in.csvのヘッダなし状態を張り付ける | csvファイルの代わりをここで定義できる |
![GS000038.png](https://qiita-image-store.s3.amazonaws.com/0/364565/9a8e08d0-62ec-f25a-932e-6e217f64338c.png)

[tFileInputDelimited]と[tLogRow]を結んでいたrow1を[tFixedFlowInput]と[tLogRow]が結ばれるように変更します。
![GS000039.png](https://qiita-image-store.s3.amazonaws.com/0/364565/6906ac31-d988-df8b-2af9-e9d33d6c0e02.png)

[tLogRow]と[tFileOutputDelimited]の[同期カラム]ボタンを押してrow定義を更新します。
![GS000040.png](https://qiita-image-store.s3.amazonaws.com/0/364565/375ea7a1-0f20-28d5-34c2-855cac55c489.png)
![GS000041.png](https://qiita-image-store.s3.amazonaws.com/0/364565/c9ab2128-572e-e3c7-3e51-4b50085fd79e.png)

[tFileInputDelimited]を無効化します。
![GS000044b2.png](https://qiita-image-store.s3.amazonaws.com/0/364565/cd781e54-fff6-75ff-6169-f136de9cb12d.png)
![GS000045.png](https://qiita-image-store.s3.amazonaws.com/0/364565/37181122-b085-6ea2-58e9-5d57868b620b.png)

これで準備は完了です。実行してみましょう。
標準出力の結果は問題なさそうです。
![GS000046.png](https://qiita-image-store.s3.amazonaws.com/0/364565/db7ca25d-2632-168b-aff0-3fe090378451.png)

out.tsvも確認しましょう。
こちらも想定どおりの出力ができました。

```csv:out.tsv
ID	NAME	GENDER
"1"	"kouda"	"男"
"2"	"mori"	"男"
"3"	"kubo"	"男"
"4"	"shimizu"	"男"
"5"	"aya"	"女"
```

##まとめ
今回はファイル入出力について確認しました。
csvでの解説でしたが、簡単に扱えることが分かってもらえたのではないでしょうか。
あらたに利用したコンポーネントと用途をおさらいしておきます。

- tFileInputDelimited
    - csvファイル読み込み
- tFileOutputDelimited
    - csv(tsv)ファイル出力
- tFixedFlowInput
    - 入力データの独自定義

毎度のことですが、ほんのさわりの部分だけを解説していますのでぜひここから深掘りしてみてください。

##次回以降
次回はデータベースI/Oをやっていきます。