Direct I/O formatted text¶
この文書では、レコードやフィールドを区切り文字によって分割する様々なデータ形式を Direct I/O で取り扱うための機能「Direct I/O formatted text」について説明します。
概要¶
Direct I/O formatted text は、Direct I/Oで以下のようなデータ形式を持つテキストファイルを読み書きするための汎用的な機能を提供します。
- レコード間が改行文字で区切られている
- フィールド間が任意の1文字(タブやカンマなど)で区切られている
- フィールドの位置(並び順)がフィールドの種類に対応する
特徴¶
Direct I/O formatted text は、以下のような特徴を持っています。
多様なデータ形式を扱うきめ細かな設定が可能¶
テキストファイルのエンコーディングやフィールド間の区切り文字をはじめ、
フィールド値の整形形式やエスケープの動作設定、 NULL
や空文字に対する取り扱いなど、
様々なデータ形式に関する設定をレコード全体、及びフィールド単位にそれぞれ設定することができます。
従来、Direct I/Oでデータ取り込みを行うために事前にデータ整形処理が必要であったような場合においても、Direct I/O formatted textを利用することで直接そのようなデータを取り扱うことが可能になります。
不整合データに対する柔軟な動作設定が可能¶
データ形式の定義と実際のデータの内容に不整合があった場合に、 エラーとして異常終了とする、警告を出力して処理を継続する、または単にスキップするなど様々な動作がレコード全体、及びフィールド単位にそれぞれ設定可能です。 エラーや警告時にはエラー箇所と不整合の内容を示す詳細な情報が出力されます。
これらの機能によって想定外のデータに対して迅速に対応できるほか、外部システムやアプリケーションの仕様変更などに伴いアプリケーションとデータに不整合が発生するような場合でも、柔軟な運用、移行を可能にすることを支援します。
データフォーマットの作成¶
Direct I/O formatted text を利用したデータフォーマットを定義するには、対象のデータモデルに対応するDMDLスクリプトにDirect I/O formatted text用のデータモデル属性を指定します。
本バージョン時点で、Direct I/O formatted textは以下の2種類のデータモデル属性が利用できます。
@directio.text.tabular
@directio.text.csv
この2種類のデータモデル属性で取り扱うデータフォーマットはいずれも 概要 で示したようなテキストファイルを扱うものです。 その動作や設定可能な項目などは多くの部分で共通していますが、異なる部分は主にフィールド中のメタ文字に対する扱いと、デフォルトの設定です。 ここでのメタ文字とは、フィールド区切り文字などのファイルフォーマット自体に関わる文字のことです。
以下、それぞれのデータモデル属性が扱うデータフォーマットの概要と使い方を説明します。
@directio.text.tabular
¶
@directio.text.tabular
はフィールド中のメタ文字を「エスケープシーケンス」によって扱います。
エスケープシーケンスは「エスケープ文字+後続文字」という形式でフィールドデータとして表現します。エスケープ文字として使用する文字や、エスケープ時の動作などは @directio.text.tabular
属性の設定により細かく指定することが可能です。
デフォルトの設定はエスケープシーケンスは無効、フィールド間の区切り文字はHT(水平タブ)、といった設定を持ちます。
この形式に対応した DataFormat
の実装クラスを自動的に生成するには、対象のデータモデルに対応するDMDLスクリプトに @directio.text.tabular
を指定します。
@directio.text.tabular
document = {
"the name of this document"
name : TEXT;
"the content of this document"
content : TEXT;
};
上記のように記述してデータモデルクラスを生成すると、 <出力先パッケージ>.text.<データモデル名>TabularTextFormat
というクラスが自動生成されます。
このクラスは DataFormat
を実装し、データモデル内のプロパティが区切り文字によって分離されて順番に並んでいるようなテキストファイルを取り扱えます。
また、 単純な ファイルを入力に利用するDSL と ファイルを出力に利用するDSL の骨格も自動生成します。
前者は <出力先パッケージ>.text.Abstract<データモデル名>TabularTextInputDescription
、後者は <出力先パッケージ>.text.Abstract<データモデル名>TabularTextOutputDescription
というクラス名で生成します。必要に応じて継承して利用してください。
@directio.text.csv
¶
@directio.text.csv
は RFC 4180 で提唱されているCSVの形式に基いて、フィールド中のメタ文字を「クウォート」によって扱います。クウォート処理の基本的な動作は、フィールドにメタ文字が含まれる場合にフィールド全体をクウォート文字で囲うことで取り扱うものです。クウォート文字として使用する文字や、クウォート方式などは @directio.text.csv
属性の設定により細かく指定することが可能です。
デフォルトの設定はクウォート文字に "
(ダブルクウォート)、フィールド間の区切り文字は ,
(カンマ)、といった設定を持ちます。
この形式に対応した DataFormat
の実装クラスを自動的に生成するには、対象のデータモデルに対応するDMDLスクリプトに @directio.text.csv
を指定します。
@directio.text.csv
document = {
"the name of this document"
name : TEXT;
"the content of this document"
content : TEXT;
};
上記のように記述してデータモデルクラスを生成すると、 <出力先パッケージ>.text.<データモデル名>CsvTextFormat
というクラスが自動生成されます。
このクラスは DataFormat
を実装し、データモデル内のプロパティが区切り文字によって分離されて順番に並んでいるようなテキストファイルを取り扱えます。
また、 単純な ファイルを入力に利用するDSL と ファイルを出力に利用するDSL の骨格も自動生成します。
前者は <出力先パッケージ>.text.Abstract<データモデル名>CsvTextInputDescription
、後者は <出力先パッケージ>.text.Abstract<データモデル名>CsvTextOutputDescription
というクラス名で生成します。必要に応じて継承して利用してください。
他のデータフォーマット機能との関係¶
Direct I/O でテキストファイルを扱うには、本書で説明する Direct I/O formatted text の他にも以下のような機能を利用できます。
これらの機能と Direct I/O formatted text では提供する機能の一部が重複、または類似しているため、以下ではそれぞれの機能のおおまかな差異や使い分けの指針を説明していきます。
Attention
ここで説明する内容は現時点のもので、将来のバージョンで変更される可能性があります。
Direct I/O CSV¶
Direct I/O CSV と Direct I/O formatted text ( @directio.text.csv
) は両者とも RFC 4180 で提唱されているCSVの形式に基づいたデータフォーマットを扱う機能です。
機能面では、 Direct I/O formatted text は Direct I/O CSV よりも細かいデータフォーマットの指定が可能で、不整合データの取り扱いも柔軟に設定することができます。 Direct I/O CSV を利用する場合には事前にフォーマット整形が必要となるようなケースでは、Direct I/O formatted text によってより効率のよい対応が可能となる場合があります。
性能面では、現時点において Direct I/O CSV は Direct I/O formatted text よりも高速に動作します。 パフォーマンス差異の度合いは実行環境や扱うファイルの特性にも変わりますが、手元の検証ではおおよそ20%から30%程度、 Direct I/O CSV のほうが高速に動作するようです。
これらの機能の特性を考慮し、また実際に取り扱うデータフォーマットや実行環境の特性に応じて機能を選択するとよいでしょう。
Direct I/O TSV¶
Direct I/O TSV は TSV形式のデータフォーマットを使う機能ですが、 TSV形式のデータフォーマットについては Direct I/O formatted text を利用することを推奨します。
Direct I/O TSV は本バージョンでは非推奨機能です。その主な理由は本機能で対応可能なデータフォーマットが制限的で、汎用性に乏しいことによります。また不整合データの取り扱いについても他のデータフォーマット機能と比べて劣る部分があります。
なお、現時点で今後 Direct I/O TSV に関して大幅な拡張や変更を行う予定はありません。
Direct I/O line¶
Direct I/O line はファイル内の行文字列とデータモデル内の1つの文字列型プロパティをマッピングするシンプルな機能を提供します。
Direct I/O lineが想定する用途は主に2つあり、1つは JSON や LTSV といった、レコードが1行で表現されるがデータの構成に区切り文字やフィールドの位置以外を利用するテキストデータフォーマットを取り扱う場合です。このような用途では引き続き Direct I/O line の利用を推奨します。
もう1つは、CSVやTSV形式の入力ファイルを扱いたいが、Direct I/O CSV や Direct I/O TSV が提供する機能では直接扱うことができず、テキスト内容の整形や形式変換、バリデーションチェックなどの事前処理が必要となる場合です。 このようなケースのいくつかは Direct I/O formatted text が提供する機能によって、直接データを扱うことが可能となる場合があります。
データフォーマットの設定¶
@directio.text.tabular
および @directio.text.csv
属性の要素には、データフォーマットに関する次のような設定を指定することができます。
- テキスト全体の構成
- ファイルヘッダの構成
- データ型の形式
- 入力時の動作
- 出力時の動作
- エスケープ方式 (
@directio.text.tabular
のみ ) - クウォート方式 (
@directio.text.csv
のみ )
ここで指定する設定項目のうち、データフィールドに対して適用される設定については、全てのデータフィールドに共通の設定値として適用されます。 データフィールド単位で個別に設定を指定したい場合は、 後述の データフィールドの設定 を行うことでデータフィールド単位に設定を上書きすることができます。
以下はDMDLスクリプトの記述例です。
@directio.text.tabular(
charset = "ISO-2022-JP",
header = force,
compression = "gzip",
true_format = "1",
false_format = "0",
date_format = "yyyy/MM/dd",
datetime_format = "yyyy/MM/dd HH:mm:ss",
)
model = {
...
};
テキスト全体の構成¶
charset
ファイルの文字セットエンコーディングを表す文字列。
指定した文字セットエンコーディングが ASCII または ASCIIの上位互換 のいずれでもない場合、 入力データの分割 が行われなくなる。
既定値:
"UTF-8"
compression
ファイルの圧縮形式。
"gzip"
またはCompressionCodec
[1] のサブタイプのクラス名を指定する。ここで指定した圧縮形式で対象のファイルが読み書きされるようになるが、代わりに 入力データの分割 が行われなくなる。
既定値: 未指定 (圧縮無し)
line_separator
ファイル出力時に使用する、レコード間を区切るテキストの改行文字。以下のオプションから指定する。
unix
: LF のみwindows
: CRLF の組み合わせ
入力時にはこの設定を利用せず、 LF, CR, CRLF のいずれも改行として扱う。 ただし CR のみの場合には 入力データの分割 が行われなくなる。
入力の末尾に改行文字が出現した場合、EOFとして扱う(次行を空レコードとして取り扱わない)。
既定値:
@directio.text.tabular
:unix
@directio.text.csv
:windows
field_separator
フィールド間の区切り文字。任意の1文字を指定する。
"\r"
(CR),"\n"
(LF), 及びescape_character
で指定した値は指定できない。既定値:
@directio.text.tabular
:"\t"
(HT:水平タブ)@directio.text.csv
:","
(カンマ)
ファイルヘッダの構成¶
header
ファイルヘッダの処理方法。以下のオプションから指定する。
nothing
: 何もしないforce
: 入力時に先頭行をスキップし、出力時に先頭行にヘッダを出力するskip
: 入力時に先頭行がヘッダにマッチすればスキップし、出力時はヘッダを出力しないauto
: 入力時に先頭行がヘッダにマッチすればスキップし、出力時に先頭行にヘッダを出力する
既定値:
nothing
データ型の形式¶
true_format
データモデルの論理値型 (
BOOLEAN
) でTRUE
を表す文字列。false_format
,null_format
と同じ文字列は使用できない。trim_input
を利用した場合、true_format
の前後に空白文字が含まれているとマッチしない。既定値:
"true"
false_format
データモデルの論理値型 (
BOOLEAN
) でFALSE
を表す文字列。true_format
,null_format
と同じ文字列は使用できない。trim_input
を利用した場合、false_format
の前後に空白文字が含まれているとマッチしない。既定値:
"false"
number_format
データモデルの数値型 (
INT
,LONG
,FLOAT
,DOUBLE
,DECIMAL
,BYTE
,SHORT
) の形式。DecimalFormat
[2] の形式で指定する。null
を指定した場合は未指定として扱う。 未指定の場合はDirect I/O formatted textが規定する標準の方式で解析、及び出力を行う。既定値: 未指定
decimal_output_style
データモデルの10進数型 (
DECIMAL
) の出力形式。以下のオプションから指定する。plain
: 指数表現なしscientific
: 必要ならば、指数表現を10^n
の単位で行うengineering
: 必要ならば、指数表現を10^(n*3)
の単位で行う
入力時にはこの設定を利用せず、全ての形式に対応する。
該当フィールドに
number_format
が指定されている場合、decimal_output_style
で指定した内容は無視される。既定値:
scientific
date_format
データモデルの日付型 (
DATE
) の形式。SimpleDateFormat
[3] の形式で指定する。既定値:
"yyyy-MM-dd"
datetime_format
データモデルの日時型 (
DATETIME
) の形式。SimpleDateFormat
の形式で指定する。既定値:
"yyyy-MM-dd HH:mm:ss"
null_format
NULL
値を表す形式。任意の文字列を指定する。null
を指定した場合は未指定として扱う。NULL
値が未指定の場合、以下のような動作となる。- 入力データには
NULL
を表す値を含められない。 - 出力データに
NULL
が含まれる場合にはon_unmappable_output
の設定に従ってエラー処理を行い、その結果ファイルの出力が実行される場合には、空文字列が出力される。
@directio.text.tabular
を利用する場合には、null
値の指定はescape_sequence
の設定も利用される。その場合の動作を以下に示す。null_format
が未指定である場合、escape_sequence
で定義したnull
値の設定を利用する。escape_sequence
でもnull
値が未指定の場合、上記に示す「NULL
値が未指定の場合」と同じ動作となる。null_format
とescape_sequence
に両方null
値が設定されている場合、null_format
の設定が優先して利用される。
既定値: 未指定
- 入力データには
[1] | org.apache.hadoop.io.compress.CompressionCodec |
[2] | java.text.DecimalFormat |
[3] | java.text.SimpleDateFormat |
入力時の動作¶
trim_input
入力時に、フィールドの先頭末尾の空白文字を除去するかどうか。以下のオプションから指定する。
true
: 除去するfalse
: 除去しない
この操作によってフィールドが空になった場合、
skip_empty_input
の対象となる。既定値:
false
skip_empty_input
入力時に、フィールドの文字列が空である場合の動作。以下のオプションから指定する。
true
: 読み飛ばすfalse
: 空文字列として扱う
既定値:
false
on_malformed_input
入力時に、不正なフィールド文字列が検出された場合の動作。以下のオプションから指定する。
error
: エラーログを出力して、異常終了する。report
: 警告ログを出力して、プロパティにNULL
を設定する。ignore
: プロパティにNULL
を設定する。
既定値:
error
on_more_input
入力時に、レコードに余剰フィールドが検出された場合の動作。以下のオプションから指定する。
error
: エラーログを出力して、異常終了する。report
: 警告ログを出力して、余剰フィールドを無視する。ignore
: 余剰フィールドを無視する。
既定値:
error
on_less_input
入力時に、レコードにフィールドが不足している場合の動作。以下のオプションから指定する。
error
: エラーログを出力して、異常終了する。report
: 警告ログを出力して、プロパティにNULL
を設定する。ignore
: プロパティにNULL
を設定する。
既定値:
error
出力時の動作¶
on_unmappable_output
出力時に、不正な文字が含まれている場合の動作。以下のオプションから指定する。
error
: エラーログを出力して、異常終了する。report
: 警告ログを出力して、そのまま出力。ignore
: そのまま出力。
データ内にエスケープやクウォートで対処できないメタ文字や、マッピングが未指定で
NULL
が存在した場合などに該当する。既定値:
error
エスケープ方式¶
エスケープ方式の設定は、 @directio.text.tabular
属性に対してのみ有効。
escape_character
エスケープシーケンス(エスケープ文字+後続文字)で使用するエスケープ文字。任意の1文字を指定する。
"\r"
,"\n"
, 及びfield_separator
で指定した値は指定できない。既定値: 未指定 (エスケープシーケンスを利用できない)
escape_line_separator
改行文字をエスケープ可能にするかどうか。以下のオプションから指定する。
true
- 改行文字をエスケープ可能にする。このオプションを指定した場合、 入力データの分割 が行われなくなる。false
- 改行文字をエスケープ不可能にする。
この設定を利用するには
escape_character
も定義する必要がある。既定値:
false
escape_sequence
利用可能なエスケープの一覧。マップ形式 (
{ "キー":"値", "キー":"値", ... }
) で指定する。- キー
キーにはエスケープシーケンスの後続文字(エスケープ文字を除いた1文字)を指定する。
キーには
"\r"
,"\n"
といった、改行文字の構成要素を含められない。 改行文字のエスケープするための設定はescape_line_separator
で指定する。- 値
値にはシーケンスに対応する1文字を指定する。
値にはNULLを表す特別なシンボル
null
を利用出来る。 フィールド全体がそのシーケンスのみの値である場合、そのフィールド値はNULLとしてエスケープされる。
サロゲートペアはキー・値のいずれにも利用できない。
この設定を利用するには
escape_character
も定義する必要がある。既定値: なし
クウォート方式¶
クウォート方式の設定は、 @directio.text.csv
属性に対してのみ有効。
quote_character
フィールドのクウォートで使用するクウォート文字。
"\r"
,"\n"
, 及びfield_separator
で指定した値は指定できない。既定値:
"\""
(ダブルクウォート)allow_linefeed
フィールドにLF(改行文字)を含められるかどうか。以下のオプションから指定する。
true
: 含められる。このオプションを指定した場合、 入力データの分割 が行われなくなる。false
: 含められない。フィールドにLFが含まれる場合はエラーとして扱う。
既定値:
false
quote_style
出力時のクォート方式。以下のオプションから指定する。
always
: 常にクウォートを行う。never
: 常にクウォートを行わない。フィールドに CR, LF,field_separator
,quote_character
のいずれかが含まれる場合はエラーとして扱う。needed
: フィールドに CR, LF,field_separator
,quote_character
のいずれかが出現した場合のみクウォートを行う。
入力時にはこの設定を利用せず、全てのクウォート方式に対応する。
既定値:
needed
header_quote_style
出力時ヘッダのクォート方式。以下のオプションから指定する。
always
: 常にクウォートを行う。never
: 常にクウォートを行わない。フィールドに CR, LF,field_separator
,quote_character
のいずれかが含まれる場合はエラーとして扱う。needed
: フィールドに CR, LF,field_separator
,quote_character
のいずれかが出現した場合のみクウォートを行う。
入力時にはこの設定を利用せず、全てのクウォート方式に対応する。
未指定の場合、
quote_style
と同じクウォート方式を利用する。既定値: 未指定
データフィールドの設定¶
Direct I/O formatted text が扱うテキストファイルのデータフィールドに関する設定は、DMDLスクリプトのデータモデルに含まれるそれぞれのプロパティに @directio.text.field
属性を指定します。
@directio.text.field
属性の要素には、次のような設定を指定することができます。
その他、データフィールドに対する個別の属性を利用した、次のような設定を指定することができます。
以下はDMDLスクリプトの記述例です。
@directio.text.tabular (
...
)
model = {
@directio.text.field (
name = "数量",
null_format = "",
on_unmappable_output = report,
)
amount : INT;
};
フィールドの基本情報¶
name
フィールド名を表す文字列。
header
の設定によりファイルヘッダを出力する場合、ここで指定したフィールド名がヘッダに利用される。未指定の場合、プロパティ名がヘッダに利用される。既定値: 未指定
フィールドのデータフォーマット¶
データフォーマットの設定 が持つ設定のうち、次の項目については @directio.text.field
属性に同名の要素を指定することでデータフィールド単位に設定を上書きすることができます。
フィールドの除外¶
データモデルに定義されている特定のプロパティをデータフィールドとして取り扱いたくない場合の設定です。
@directio.text.ignore
- このフィールドをデータフィールドとして取り扱わない。
ファイル情報の取得¶
入力時のテキストファイルに関する情報を取得する場合、それぞれ次の属性をプロパティに指定します。
これらの属性はファイル入力時のみ有効です。 これらの属性を指定したプロパティは、ファイル出力時にはデータフィールドから除外されます。
@directio.text.file_name
このフィールドに、該当データレコードが含まれるファイルパスを設定する。
この属性を指定するプロパティには
TEXT
型を指定する必要がある。@directio.text.line_number
このフィールドに、該当データレコードの開始行番号(テキスト行番号)を設定する。
この属性を指定するプロパティには
INT
またはLONG
型を指定する必要がある。この属性が指定された場合、 入力データの分割 が行われなくなる。
@directio.text.record_number
このフィールドに、該当データレコードのレコード番号を設定する。
この属性を指定するプロパティには
INT
またはLONG
型を指定する必要がある。この属性が指定された場合、 入力データの分割 が行われなくなる。
設定例¶
エスケープシーケンス¶
@directio.text.tabular
でエスケープシーケンスを利用するための設定例です。
ここでは以下のようなエスケープシーケンスを定義します。
\
をエスケープ文字に指定- 改行文字
\r
,\n
, タブ\t
をエスケープ - エスケープ文字自体をエスケープ
\N
をNULLとして扱う
@directio.text.tabular (
escape_character = "\\",
escape_sequence = {
"r" : "\r",
"n" : "\n",
"t" : "\t",
"\\" : "\\",
"N" : null,
},
)
...
Note
DMDLスクリプト内ではJavaの文字列リテラルと同様に \
はエスケープシーケンスとして扱われるため、各要素の値に \
を指定したい場合は "\\"
のようにバックスラッシュを2つ記述します。
空文字列とNULLの扱い¶
Direct I/O formatted textでは、空文字列とNULLに関して標準では以下のように設定されています。
skip_empty_input = false
(フィールド値が空値の場合は空文字列として扱う)null_format = (未指定)
これらの設定により、標準の動作は以下のような強い制約を伴います。
- 入力ファイル内のフィールド値が空文字列となっている場合、そのフィールドが
TEXT
型以外のプロパティと対応付けられていると不正な値として扱われる。 - 出力時にデータモデル内のプロパティ値に
null
が含まれると不正な値として扱われる。
データモデル全体で空文字列を NULL
として扱う場合は、以下のように null_format
を設定します。
@directio.text.csv (
null_format = "",
)
...
Note
上記のデータモデル全体で空文字列を NULL
として扱う動作は Direct I/O CSV と同じ動作となります。
Direct I/O CSV から Direct I/O formatted text ( @directio.text.csv
) に移行するなどで、 Direct I/O CSV と同様の動作に設定したい場合には上例のように設定してください。
数値型のプロパティのみに対して空文字列を NULL
として扱うなど、フィールド単位で null_format
を設定することもできます。
@directio.text.csv (
...
)
model = {
@directio.text.field (
null_format = "",
)
amount : INT;
};
null_format
による設定のほかに、不正な値を検出した場合の動作を変更し処理を続行させる方法もあります。
以下の設定は、数値型のフィールドに空文字列などの不正なフォーマットを検出した場合に警告を出力し、空文字列と null
を相互にマッピングします。
@directio.text.csv (
...
)
model = {
@directio.text.field (
on_malformed_input = report,
on_unmappable_output = report,
)
amount : INT;
};
Attention
null_format
が未指定の場合、テストドライバのジョブフローやバッチのテスト実行時にテストドライバが NULL
を取り扱う動作にも注意が必要です。
例えば Excelによるテストデータ定義 などの方法で入力データを定義する際には、テストケースで利用しないプロパティを未定義にすることができますが、その際テストドライバは未定義のプロパティをNULLとして取り扱います。また同様に空のセルもNULLとして扱います。
テストドライバの NULL
値の扱いについては、 Excelによるテストデータ定義 などのテストドライバのドキュメントを確認してください。