努力したWiki

推敲の足りないメモ書き多数

ユーザ用ツール

サイト用ツール


documents:etl:pentaho:pentaho-016

109.パック形式を扱ってみる

2026-05-29
パック形式の説明を追加

パック形式の数値データ

ゾーン形式と異なりパック形式だとテキストエディタで確認するのは無理があるので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に仕様を伝えて生成してもらい少しだけ手を入れました。
だいぶ好みのロジックにしてくれるようになってきていてちょっと楽しい。

Javaを使わない場合

別のAIのGrokさんが突っ込んできたんで掲載はしてみるけど、メンテしなきゃならない範囲を考えるとJavaを使う方法が絶対楽ですよ。ええ。

項目QTYのバイナリを16進数の文字列に変換します。

16進数の文字列の最後の文字とそれ以前に分割します。項目QTY-REIRに一番最後の文字が入り、“C”,“F”,“D”のいずれかになるはずです。

項目QTY-REIRの内容で項目QTY-SIGNに-1 or 1 を設定します。“D”の時に-1、それ以外は1ですね。
項目QTY-AFTERに項目QTY-FRONTを数値に変換して格納します。パック形式の16進数の文字列なので、一番最後の文字を除けば10進数の文字列になっています。

項目QTY-CALCEDに 項目QTY-AFTER × 項目QTY-SIGN の結果を格納する事で、パック形式を変換できたことになります。

あとは同様に名称を QTY-CALCED → QTY に変更してファイルに書き出せば終わりです。
バイナリデータを連続した16進数文字列に出来る手段があるとこんな感じで楽ができます。
ですがJavaを使う方法と比べてそんな楽になったような気はしません。

documents/etl/pentaho/pentaho-016.txt · 最終更新: by k896951

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki