• ベストアンサー

どなたか知恵をお貸しください。

下記のような、データ加工プログラムをJavaで書こうと思っているのですが 暗礁に乗り上げています。 どなたか、良い知恵(どのようなアルゴリズムが考えられるか、等)を お貸しいただけないでしょうか? よろしくお願いいたします。 【元ファイルのビット列】 ・・・・00000001 00011100 00000000 10000100 01001100・・・・・ ↓「00000001 00011100」の先頭6ビットを削除 【新規ファイルに書きこみ】  01000111 00 ↓以降のビット列をそのまま新規ファイルに追加書きこみ 【書きこみ結果】  01000111 00000000 00100001 00010011 00・・・・・ 【処理概要】 1.バイナリファイル(サイズは不特定)を先頭から読みこむ。 2.00000001 00011100というビット列が現れるまで、読み捨てていく。 3.上記のビット列が現れたら、00000001の先頭6ビットを削除し、  その結果を新規ファイルに書きこむ。  このビット列が元ファイルの何バイト目に現れるかは、その都度違う。 4.それ以降のビット列(ファイルの終端まで)をすべて新規ファイルに追加書きこみしていく。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

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配列とする」などの改良を加えていくと良いでしょう。

masamisss
質問者

補足

丁寧なご回答、ありがとうございました。 たいへん参考になりました。なんとかできそうな気がします。 ただ1点、わからないことがあります。 >(6-1)先頭から8要素を1バイトに変換して、ファイルに書き出す。 これがよくわかりません。 8要素(True or False)をひとつひとつ取り出しつつ 10進数に変換して、それをwriteするという意味なのでしょうか? それとも、そのための有用なメソッドがクラスライブラリに定義されているのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • aton
  • ベストアンサー率47% (160/334)
回答No.3

おおよそ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)を出力ファイルに書き込んで終了 …と,こんな感じでしょうか。 #適当に書いたのでもしかしたら破綻してるかもしれませんが,大筋はこんな感じでいいと思います。

masamisss
質問者

お礼

なるほど。ビットシフトをこういう風に活用すれば ビット操作&ファイルへの書き出しはスムーズに行きますね。

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

「10進数に変換」する必要があるかどうかは不明ですが、 「8個のbooleanを数値にする」のです。 (2)と逆の処理です。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • [VBS] 16進数でバイナリファイル出力したい

    すいません、教えて下さい。 VBSを利用して16進数にてバイナリファイルを生成したいです。 例えばSJIS文字コードの文字列"あ"の場合だと16進数では"82A0"です。 その"82A0"を指定してバイナリファイル出力を行いたいです。 自分で色々と試しましたが、何故か出力ファイルの結果がバイナリで"81 45 A0"となってしまい 結果的に"あ"が表示されません、、、。 目的としてはVBSでビット演算子の論理和による暗号化を行いたいです。 申し訳ありませんが、ご教示頂ければ幸いです。

  • テキスト操作

    できるかどうか曖昧なのでこの場で質問させていただきます。 VBからテキストに書き込みを行う処理なんですが、 まず 111111 と先頭行に書かれたテキストファイルがあります。 これから新たに先頭行に"2222222"を追加します。 (ここからVBの処理で) 222222 111111 また先頭行に"333333"を追加します。 ここで"11111111"を削除します。 333333 222222 つまりテキストファイルが3行以上に達すると下から削除していく動きです。(ところてん式に押し出すイメージですね) こうゆう動きってVBで可能でしょうか? 僕が調べた限りでは不可能な気がします。 もし、代替案があればご指導いただきたいと思ってます。

  • 外部ファイルから特定の値を取り出して、値ごとに新しいファイルを生成して書き込むには?

    こんにちわ。質問させてください。 ひとつのCSVファイルがあります。1列目の先頭の値はランダムねアルファベットです。 aという値が先頭にある列は、a.csvを生成して、a.csvにaの行を書き込みます。b,cも同様にb.csv,c,csvを生成して書き込みます。 要するに一枚のファイルから値ごとに新しいファイルを生成して書き込みをしたいのです。新しくできたファイルは追加書き込みをしないでの上書きモードです。substr関数を使って値を取り出すまではわかるのですが、そこからの処理がわかりません。どうぞ教えてください。よろしくおねがいします。

    • ベストアンサー
    • Perl
  • ファイルの途中に文字列を挿入

    こんにちは。プログラミング初心者で、初めて質問させていただきます。勉強中に思ったのですが、 ファイルの書き込みについてなのですが、あるファイルに既にデータがあり、その先頭部分(あるいは途中)にある文字列を追加挿入しなければならなくなった場合どういった処理をすることになるのでしょうが? fseekなどで場所を指定して書き込んでしまうと、そこの文字列が上書きされてしまうと思うのですが。

  • 82 00 00 41で始まるバイナリ

    サイズの大きなバイナリファイルを入手しました。 ダンプすると先頭は 82 00 00 41~ でした。 ダンプの最後は 05 F0があって、そのF0以降はたくさんの00でした。 思い当たるファイルフォーマットはありませんでしょうか?

  • バイナリファイルの操作(配列の操作について)

    こんにちは。 大変お世話になっております。 配列要素の先頭[0]から[5]までを文字列N、[6]から[1029]までをバイナリデータの計1030バイトの配列要素を使用しています。 [現在行なっている操作方法] 1. Buf[1500]とBuff[1500]を用意 2. fread関数により、Bufに1024バイトずつ格納 3. sprintf関数により、Buffの先頭[0]から[5]まで文字列挿入 4. strcat関数により、BuffとBufを結合 と言う形をとっています。 そこで、sprintfにて先頭から[5]までの文字列を挿入後、先頭から[5]までの配列要素を削除(不要になるため)し、バイナリデータのみにしたいのですが、何か方法はありますでしょうか? NNNNNNDDDDDDDDDDDDDDDDD・・・・・DDDDD←1029番 から NNNNNNを削除し、 DDDDDDD・・・・・DDDDD のみにしたいと思っています。 よろしくお願いします。

  • SED.exeがwindows7で動かない

    SED.exeが64bitのWindows7で動きません。 XPマシンでテキストファイルの各行の先頭に特定の文字列を追加するのに、 SEDを使用したバッチファイルを使っていたのですが、 7マシンで同コマンドを実行しようとすると 「64 ビット バージョンの Windows での非互換性のため、 プログラムまたは機能である "***\SED.EXE" を開始または実行できません。 ソフトウェア製造元に問い合わせて 64 ビット Windows 互換バージョンが利用可能であるかどうか確認してください。」 というダイアログが出て実行することができません。 どうしたらよいのでしょうか?

  • シフト演算について

    基本情報技術者試験の資格試験のための勉強をしているものです。 現在、カテゴリー的には基礎理論の離散数学、 シフト演算のうち、「論理シフト」ではなく、 「算術シフト」で理解できない点があります。 左シフトは理解できたつもりなんですが・・・ 右シフトがいまいちよくわかりません。 以下に例題を表記します。 【10001100を2ビット左シフト】 先頭ビットは符号ビットということで、マイナスの数値になるのだと思います。すると、 【元の数】 10001100 =-(0001100) =-(8+4) =-12 【2桁左シフト結果=元の数×2^2】 10110000 =-(0110000) =-(32+16) =-48 となり、 元の数=-12 結果 =-48 で、結果が元の数×2^2で結果が合っているようです。 (と思っているだけなんですが) 元の数の考え方自体に間違いがありそうですが・・・ とりあえず進みます。 同様に 【10001100を2ビット右シフト】すると 【2桁右シフト結果=元の数×2^-2(=元の数×1/4)】 11100011 =-(1100011) =-(64+32+8+4) =-99 となり、 元の数=-12 結果 =-99 で、結果が元の数×2^-2(=元の数×1/4)と結果が合いません。 先頭符号を空いたビットに移動した部分は数えないのでしょうか。 すると、 元の値 =-12 結果  =-3 で結果が合う気がします。 過去の回答や検索サイトなどで調べてみましたがピンときません。 テキストにも、10進数での数値表記はなく、 答え合わせができなくて困っております。 どなたかお答えいただけると助かります。 どこが間違っているのか混乱しております。 先頭ビットが正負の符号ビットという前提の例題なのですが、 マイナス符号がついている前提となるので 先頭ビットや空いたビットに入れた符号ビットも含めて 「2の補数」で考える必要があるのかどうかも よくわからなくなってきました。 つまり、元の数値「10001100」は「-12」ではなく -(01110100) =-(64+32+16+4) =-116 なのでしょうか なお、C言語は今のところ学習していないので、 C言語にまつわるご回答ですともっとわからなくなりそうです。 単純に間違いを指摘していただけると大変助かります。 よろしくお願いします。

  • 特定の桁数を抽出

    教えてください。 エクセルのVBAで、 特定の桁数を抽出するにはどうすれば、よいでしょうか。 イメージは、添付ファイルのC列のようなVBAを作りたい、 と考えています。 条件としては、 (1)先頭~10桁までを抽出 (2)それ以降は削除 (3)文字列にする、 です。 使用ソフトは、EXCEL2010です。 よろしくお願いします。

  • UTF-8での保存について

     エディットボックスに入力してある日本語の文字列をUTF-8やUTF-8Nでテキストファイルに保存したのですがうまくいきません。  UTF-8の場合はファイルの先頭に3バイトのBOMをつければいいらしいので、 ファイルの先頭に0xEF,0xBB,0xBFの3バイトを追加してテキストファイルに保存しましたがメモ帳で開くと文字化けします(メモ帳で開くときは文字コードをUTF-8にして開いてます)。 作成したテキストファイルをバイナリエディタで開いてみると先頭の3バイトはEFBBBFとなっているので何も問題はないと思うのですが、どうして文字化けするファイルができてしまうのでしょうか? --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C言語