ExcelでDSLしてみよう
それでは実際にExcelを使った外部DSLっぽいミニフレームワークを作成してみましょう。通常のプログラムやXMLと比較して、
メリット
Excelは表ですので、
デメリット
デメリットとしては、
今回のお題
今回のお題は
例で使用する
表1が電文のフォーマットやルールを記述した
この仕様書をもとに固定長電文を解析してから、
1234567890123456789012345678901234567890123 20081101user1 [email protected] 10 20081101user2 [email protected] 0 20081101user3 [email protected] 100 20081102user4 [email protected] 80 20081102user5 [email protected] 55
No | データ名称 | 開始 | 長さ | 変換ルール |
---|---|---|---|---|
1 | 送信日 | 1 | 8 | Date型に変換 |
2 | ユーザ名 | 9 | 10 | 両端空白除去 |
3 | メールアドレス | 19 | 20 | 両端空白除去 |
4 | ポイント | 39 | 5 | 両端空白除去 Integer型に変換 |
Step1:ベタなコードで書いてみる
まずはDSLなどを使わずにべたにコードを書くとリスト1のようになります。
まず①で固定長電文のファイルを読み込み、
parseメソッドはデータの読み込み処理です。データがなくなるまで読み込み処理を繰り返します。④でそれぞれのデータ項目のサイズだけ順番にデータを読み込んでいます。同時にDate型への変換
public static void main(String[] args) throws Exception {
byte[] messages = FileUtils.readFileToByteArray( ┓
new File("data.txt")); ┛①
MessageParser parser = new MessageParser(messages); ―②
parser.parse();
}
private static class MessageParser {
private int index = 0;
private final ByteArray bytes;
public MessageParser(byte[] bytes) { ┓
this.bytes = new ByteArray(bytes); |
} ┛③
public void parse() {
while (index < bytes.getLength() - 1) {
Map<String, Object> record =
new HashMap<String, Object>();
record.put("送信日", toDate(getString(8))); ┓
record.put("ユーザ名", trim(getString(10))); |
record.put("メールアドレス", trim(getString(20))); |
record.put("ポイント", toInteger(trim(getString(5)))); ┛④
System.out.println(record); ―⑤
}
}
private String getString(int length) {
String value = bytes.getString(index, length);
index += length;
return value;
}
private static Integer toInteger(String value) { ... }
private static String trim(String value) { ... }
private static Date toDate(String value) { ... }
}
{送信日=Sat Nov 01 00:00:00 JST 2008, ポイント=10, ユーザ名=user1, メールアドレス[email protected]} {送信日=Sat Nov 01 00:00:00 JST 2008, ポイント=0, ユーザ名=user2, メールアドレス[email protected]} {送信日=Sat Nov 01 00:00:00 JST 2008, ポイント=100, ユーザ名=user3, メールアドレス[email protected]} {送信日=Sun Nov 02 00:00:00 JST 2008, ポイント=80, ユーザ名=user4, メールアドレス[email protected]} {送信日=Sun Nov 02 00:00:00 JST 2008, ポイント=55, ユーザ名=user5, メールアドレス[email protected]}
考察1:MessageParserがクラスになっているのはなぜ?
MessageParserクラスは連載の前回でもお勧めしたインナークラスとして実装されています。これはバイト配列の現在の読み込み位置である変数indexをフィールドとして保持したいからです。
もしクラス化せずにローカル変数で保持しようとすると、
Map<String, Object> record = new HashMap<String, Object>();
record.put("送信日", toDate(bytes.getString(index, 8)));
index += 8;
record.put("ユーザ名", trim(bytes.getString(index, 10)));
index += 10;
また、
ByteReader reader = new ByteReader(bytes);
String sendedDate = reader.readAsString(8);
String userName = reader.readAsString(10);
考察2:これからどうする?
リスト1はベタに書かれていて、
今回は電文内のデータ項目は4種類