- ベストアンサー
どなたか知恵をお貸しください。
下記のような、データ加工プログラムをJavaで書こうと思っているのですが 暗礁に乗り上げています。 どなたか、良い知恵(どのようなアルゴリズムが考えられるか、等)を お貸しいただけないでしょうか? よろしくお願いいたします。 【元ファイルのビット列】 ・・・・00000001 00011100 00000000 10000100 01001100・・・・・ ↓「00000001 00011100」の先頭6ビットを削除 【新規ファイルに書きこみ】 01000111 00 ↓以降のビット列をそのまま新規ファイルに追加書きこみ 【書きこみ結果】 01000111 00000000 00100001 00010011 00・・・・・ 【処理概要】 1.バイナリファイル(サイズは不特定)を先頭から読みこむ。 2.00000001 00011100というビット列が現れるまで、読み捨てていく。 3.上記のビット列が現れたら、00000001の先頭6ビットを削除し、 その結果を新規ファイルに書きこむ。 このビット列が元ファイルの何バイト目に現れるかは、その都度違う。 4.それ以降のビット列(ファイルの終端まで)をすべて新規ファイルに追加書きこみしていく。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
I/Oはバイト単位が最小ですから、ビット単位のI/Oを行おうとすると面倒ですね。 次のような処理手順で出来ないでしょうか。 基本方針:処理途中のデータはboolean配列として格納する。ファイルが小さいことがわかっているならファイル全体をその配列に格納するが、ある程度の大きさがある、またはその可能性があるなら「ある程度を読む、処理する、ある程度を書く」の繰り返しにする。 // 初期化 (1)最初はboolean配列は長さゼロ。 // ここからループ // 読み出し (2)ファイルの終端に達したら(8)へ。 (3)ファイルから1バイト読んで、8個のbooleanを追加する。 (4)boolean配列が長さ16未満なら(2)へ。 // 主たる処理 (5)boolean配列の先頭から16個の要素が、【処理概要】2のパターンなら (5-1)先頭6要素を削除する。 // 書き出し (6)boolean配列が長さが8以上なら、 (6-1)先頭から8要素を1バイトに変換して、ファイルに書き出す。 (6-2)その後boolean配列の先頭から8要素を削除する。 (7)(2)へ。 // ここまでループ // 後始末 (8)boolean配列が長さが1~7なら、 (8-1) 8-(長さ)分の詰め物をして、1バイトに変換する。 (8-2) そのバイトをファイルに書き出す。 上記を元に、高速化のために「boolean配列は仮想的なものとして、実際のデータはbyte配列とする」などの改良を加えていくと良いでしょう。
その他の回答 (2)
- aton
- ベストアンサー率47% (160/334)
おおよそhappy_peopleさんの書かれた方法でいいと思うんですが,boolean配列を使わずbyteにシフト演算を行ったほうが楽なのではないかと思います。 処理の流れはだいたい以下のような感じです。 1) ファイルからバイト列を読み込む '00000001 00011100'が見つかるまでそのバイト列を別ファイルに出力 (該ビット列の出現判定は,例えば「連続する2バイトに対し,それぞれ 0x1, 0x1C とのXORを取って結果がゼロになるかどうか」などとすればよいでしょう) 2) 見つかったら, 2-1) まず1バイト目(b1)を6ビット左にシフト: bf = b1 << 6; 2-2) 次に2バイト目(b2)を2ビット右にシフト: bt = b2 >>> 2; 2-3) bfとbtのORを取って出力するバイト値(b)を生成: b = bf | bt 2-4) bを出力ファイルに書き込む 2-5) b2をb1に代入し,次の処理に備える 3) 以後,次の1バイトをb2に読み込み, 2-1~2-6の処理を行う これをb2に読み込むべきバイトが無くなるまで繰り返す 4) b2の読み込みでEOFが返ってきたら, 2-1の処理を行ったのち,そのバイト(bf)を出力ファイルに書き込んで終了 …と,こんな感じでしょうか。 #適当に書いたのでもしかしたら破綻してるかもしれませんが,大筋はこんな感じでいいと思います。
お礼
なるほど。ビットシフトをこういう風に活用すれば ビット操作&ファイルへの書き出しはスムーズに行きますね。
- happy_people
- ベストアンサー率30% (25/81)
「10進数に変換」する必要があるかどうかは不明ですが、 「8個のbooleanを数値にする」のです。 (2)と逆の処理です。
補足
丁寧なご回答、ありがとうございました。 たいへん参考になりました。なんとかできそうな気がします。 ただ1点、わからないことがあります。 >(6-1)先頭から8要素を1バイトに変換して、ファイルに書き出す。 これがよくわかりません。 8要素(True or False)をひとつひとつ取り出しつつ 10進数に変換して、それをwriteするという意味なのでしょうか? それとも、そのための有用なメソッドがクラスライブラリに定義されているのでしょうか?