- ベストアンサー
初めて質問させていただきます。
初めて質問させていただきます。 javaでバイナリデータをファイルに保存したいのですが、どのようにファイルに書き出すべきなのかわかりません。 ここでいうバイナリデータなのですが、適切かわかりませんがCOBOLへ渡すデータとなります。 説明不足ならば申し訳ありませんが、お助けください。 よろしくお願いいたします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>・作成側の環境はLinux上で、Javaにて作成します。 >・作成データは基本数値のみです。 > 一部数値の最後に「c」や「ffff」の付加があります。 であれば、intもしくはlongをPacked-Decimal形式にして出力できれば大丈夫そうですね。 参考にint値をPacked-Decimal形式に変換するメソッドを作ってみました。 バグが有るかも知れませんが。 なお、文字数の都合でアクセス修飾子などは省略しています。 例) -------------------------- class PackedDecimalUtils { static final int PLUS = 0xC; // 環境によって異なる static final int MINUS = 0xD; // 環境によって異なる static final int ZONE = 0xF; // ASCII の場合は 0x3 // int値をPacked-Decimal形式に変換する。 // 戻り値は1バイトをintで表現した符号ビット付 Packed-Decimal形式のデータ static int[] convertToPackedDecimal( int value, // 変換したい元の数値 int digitNumber // 桁数 ) { // データ後ろ(下位バイト)の方から処理する。 // 1バイト分のデータを入れるオブジェクト final PackedByteData byteData = new PackedByteData(); // 桁数が偶数の場合は、符号分を入れると半バイト余るので埋めておく if (digitNumber % 2 == 0) byteData.push(ZONE); // 符号を入れる byteData.push(value < 0 ? MINUS : PLUS); // 後は絶対値を処理 int abs = Math.abs(value); if (abs >= Math.pow(10, digitNumber)) throw new IllegalArgumentException(); // 結果の要素数は(指定桁数+符号分の1つ)の半分(割り切れない場合は繰上げ) int[] result = new int[digitNumber / 2 + 1]; // 下位の桁から処理 for (int i = digitNumber - 1; i >= 0 ; i--) { if (byteData.isFill()) { result[(i + 1) / 2] = byteData.toInt(); byteData.clear(); } byteData.push(abs % 10); abs /= 10; } result[0] = byteData.toInt(); return result; } static class PackedByteData { int upper = -1; int lower = -1; void push(int value) { if (lower < 0) { lower = value; return; } if (upper < 0) { upper = value; return; } throw new IllegalStateException("This is already fill."); } boolean isFill() { return upper >= 0 && lower >= 0; } int toInt() { if (!isFill()) throw new IllegalStateException("This is not fill."); return (upper << 4) + lower; } void clear() { upper = -1; lower = -1; } } } ------------------------------ 定数ZONEはゾーンビットの値、余ったところに設定しておくものです。 定数PLUS/MINUSは符号ビットです。正負を表すマークとなります。 これらの実際の値は環境によって変わりますので、受取り先に合わせて変更してください。 なお、出力値をint型の配列で扱っていますが、0~255の値しか入りませんので、もっと小さい型でも大丈夫なはずです。 ファイルに出力する際には、1バイト分を表すint値として OutputStream.write(int) に 渡してやれば良いかと。 文字制限いっぱいなのでここまででご勘弁を。(笑)
その他の回答 (3)
- root139
- ベストアンサー率60% (488/809)
> 実際にファイルへ出力するイメージは以下の感じであってますでしょうか? 合ってます。 もし、性能が問題になるのでしたら FileOutputStream に BufferedOutputStream をかぶせることになるとになると思いますが、new 以外の部分は同じになります。 例) ------------------------------------------ final OutputStream fos = new BufferedOutputStream(new FileOutputStream(dataFile)); ---------------------------------------------- > ちなみに「0001」「000000001c」などの値も変換可能でしょうか? これは、2進数/16進数でしょうか? それとも、正の数を符号付の Packed-Decimal 形式にした際には最後に符号ビットが付きますが、最後の「c」はそれでしょうか? まず、何なのか分からないと何ともいえません。 仮に2進数/16進数だとしますと、int型/long型の変数に入れる時点の問題になるかと。 元のリテラル表現が何であれ、int型/long型の変数に入れれば同じになりますので。
- root139
- ベストアンサー率60% (488/809)
もしかして、汎用系のデータセットとして使うためのファイルを出力するということしょうか? もしそうだとしますと、int型の値からPacked-Decimalへの変換方法なども含めてのご質問ですね。 下記のことはどうなりますでしょうか? ・Java を動かす環境(PC/UNIX系OS/メインフレームなど) ・読込むCOBOLを動かす環境(PC/UNIX系OS/メインフレームなど) ・データの種類(数値のみなのか英数字も含むのか日本語なども含むのか) ・元のデータはすでに変数に入っていると仮定して良いか もし英数字や日本語を含むのであれば、文字コードを読込む環境に合わせて変換する必要が有るのかどうかも問題となります。 読込先の環境がEBCDICの可能性も有りますので。
補足
度々ご回答いただきありがとうございます! 実は今回、相手方の情報があまりにもなく困っているのです。 TRY&GOの状況なのです。。。 質問の方向性が変わってくるのかもしれませんが、 ・作成側の環境はLinux上で、Javaにて作成します。 ・作成データは基本数値のみです。 一部数値の最後に「c」や「ffff」の付加があります。 ・データは変数に格納されています。(しています)。 ・POS連携システムということで引き渡すデータを作成します。 相手方の情報は不明です。作成フォーマットのみ存在します。 そのフォーマット内に項目の属性P,Kなどとあります。Kてなんだろう・・・ 質問してて、恥ずかしいですのですが まずは変換方法から含め、ご教授いただけると助かります。
- root139
- ベストアンサー率60% (488/809)
一般的には FileOutputStream を使います。 http://www.techscore.com/tech/J2SE/IO/2.html http://java.sun.com/javase/ja/6/docs/ja/api/java/io/FileOutputStream.html そのバイナリーデータをどの様な形で持っているのかにもよりますが。
補足
ご回答ありがとうございます。 なるほど 作成したいのはバイナリの質問とは少しずれるのかもしれませんが・・・ 項目A [0001] → パックドデシマル[2byte] 項目B [000001] → パックドデシマル[3byte] みたいな固定長のファイルを作成したいです。
お礼
大変参考になりました! サンプルも非常にわかりやすく助かりました。 ありがとうございました。
補足
大変詳しくご丁寧にありがとうございます。 何から何まで申し訳ありませんが、可能ならばご教授ください。 >ファイルに出力する際には、1バイト分を表すint値として OutputStream.write(int) に >渡してやれば良いかと 実際にファイルへ出力するイメージは以下の感じであってますでしょうか? int[] a = pdc.convertToPackedDecimal(1234,4); FileOutputStream fos = new FileOutputStream (dataFile); for(int i=0;i<a.length;i++){ fos.write(a[i]); } fos.flush(); fos.close(); ちなみに「0001」「000000001c」などの値も変換可能でしょうか?