documents:etl:pentaho:pentaho-016
109.パック形式を使ってみる
ゾーン形式と異なりパック形式だとテキストエディタで確認するのは無理があるのでHEXダンプするかバイナリエディタを利用します。
以下のデータは108.ゾーン形式を扱ってみるのゾーン部分をパック形式(Packed Decimal)に変更したものになります。
COBOLで言うところの QTY PIC S9(5) COMP-3. に相当します。
こちら、パック形式バイナリのデータとしては以下となっています。
0x00 0x13 0x0C : パック形式で5桁の数値 130( 00130) 0x00 0x02 0x3C : パック形式で5桁の数値 23( 00023) 0x00 0x12 0x0C : パック形式で5桁の数値 120( 00120) 0x00 0x02 0x0D : パック形式で5桁の数値 -20(-00020)
もう今回は直にJavaで処理させました。毎度の事ですがGUI上の表示はおかしいですけど出力ファイルはきちんと想定通りになっています。
項目QTYを3バイトのバイナリとして取り込みします。そのためレコード長が108.ゾーン形式を扱ってみる で使用した1レコード52バイトではなく、1レコード50バイトになります。
Javaのコード内で、バイナリを16進数文字列に変換します。その文字列末尾をみて、“C”,“F”なら正の数値、“D”なら負の数値として文字列先頭に“-“を付与します。
パック形式なので、末尾以外は”0”~“9”の文字だけが現れる事になり、そのまま切り出してしまえば10進数の文字列になります。 この結果をBigDecimal型へ変換して、PentahoのBigNumber型項目である項目QTY-AFTERへ設定しておきます。
import java.util.HashMap; import java.util.Map; import java.util.Arrays; import java.math.BigDecimal; public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException { if (first) { first = false; } Object[] r = getRow(); if (r == null) { setOutputDone(); return false; } r = createOutputRow(r, data.outputRowMeta.size()); byte[] QTY = get(Fields.In, "QTY").getBinary(r); String QTY_item = normalizePackedHex(QTY); BigDecimal QTY_after = new BigDecimal(QTY_item); get(Fields.Out, "QTY-AFTER").setValue(r, QTY_after); // Send the row on to the next step. putRow(data.outputRowMeta, r); return true; } public static String normalizePackedHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { sb.append(String.format("%02X", b)); } int len = sb.length(); char sign = sb.charAt(len - 1); // 末尾の符号ニブル sb.deleteCharAt(len - 1); // 末尾を削除(C/D/F) switch (sign) { case 'C': // 正 case 'F': // 正(符号なし扱い) return sb.toString(); case 'D': // 負 return "-" + sb.toString(); default: // 想定外の符号ニブル return sb.toString(); } }
String normalizePackedHex(byte[] bytes)のメソッドはCopilotに仕様を伝えて生成してもらい少しだけ手を入れました。
だいぶ好みのロジックにしてくれるようになってきていてちょっと楽しい。
documents/etl/pentaho/pentaho-016.txt · 最終更新: by k896951


