バイナリ文字列 (文字どおり 1 と 0 のみを含む String オブジェクト) がある場合、それらをビットとしてファイルに出力するにはどうすればよいでしょうか?
これは、私が取り組んでいたテキスト コンプレッサー用です。それはまだ私を悩ませています、そして最終的にそれを機能させるのは素晴らしいことです. ありがとう!
バイナリ文字列 (文字どおり 1 と 0 のみを含む String オブジェクト) がある場合、それらをビットとしてファイルに出力するにはどうすればよいでしょうか?
これは、私が取り組んでいたテキスト コンプレッサー用です。それはまだ私を悩ませています、そして最終的にそれを機能させるのは素晴らしいことです. ありがとう!
運が良ければ、java.math.BigInteger がすべてをやってくれるかもしれません。
String s = "11001010001010101110101001001110";
byte[] bytes = (new java.math.BigInteger(s, 2)).toByteArray();
これは、バイト オーダー (ビッグ エンディアン) と右揃え (ビット数が 8 の倍数でない場合) に依存しますが、自分で文字変換を行うよりも後で配列を変更する方が簡単な場合があります。 .
最も簡単なのは、連続する 8 文字を取得し、それらをバイトに変換して、そのバイトを出力することです。ストリームの終わりを認識できる場合は、末尾にゼロを埋め込むか、ファイルの先頭に長さ (ビット単位) のヘッダーを追加します。
内側のループは次のようになります。
byte[] buffer = new byte[ ( string.length + 7 ) / 8 ];
for ( int i = 0; i < buffer.length; ++i ) {
byte current = 0;
for ( int j = 7; j >= 0; --j )
if ( string[ i * 8 + j ] == '1' )
current |= 1 << j;
output( current );
}
多少の調整が必要ですが、それが一般的な考え方です。
public class BitOutputStream extends FilterOutputStream
{
private int buffer = 0;
private int bitCount = 0;
public BitOutputStream(OutputStream out)
{
super(out);
}
public void writeBits(int value, int numBits) throws IOException
{
while(numBits>0)
{
numBits--;
int mix = ((value&1)<<bitCount++);
buffer|=mix;
value>>=1;
if(bitCount==8)
align8();
}
}
@Override
public void close() throws IOException
{
align8(); /* Flush any remaining partial bytes */
super.close();
}
public void align8() throws IOException
{
if(bitCount > 0)
{
bitCount=0;
write(buffer);
buffer=0;
}
}
}
その後...
if (nextChar == '0')
{
bos.writeBits(0, 1);
}
else
{
bos.writeBits(1, 1);
}
文字列が 8 ビットの倍数であると仮定すると (それ以外の場合はパディングできます)、Integer.valueOf メソッドで Java に組み込まれている解析を利用して、次のようなことを行います。
String s = "11001010001010101110101001001110";
byte[] data = new byte[s.length() / 8];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) Integer.parseInt(s.substring(i * 8, (i + 1) * 8), 2);
}
FileOutputStream
次に、バイトを非常に簡単に書き込むことができるはずです。
一方、効率を求める場合は、文字列を使用してビットを格納するのではなく、コンプレッサーで直接バイトを構築することを検討する必要があります。