Java - バイナリ/コード文字列の操作についてヘルプが必要です
-
27-09-2019 - |
質問
プロジェクトの場合、バイナリ文字列をバイト (の配列) に変換し、バイナリでファイルに書き出す必要があります。
ハフマン エンコーディングを使用してコード文字列に変換された文があるとします。たとえば、文が次のような場合です。「こんにちは」 h = 00 e = 01、l = 10、o = 11
この場合、文字列表現は 0001101011 になります。
それをバイトに変換するにはどうすればよいでしょうか?<-- もしその質問が意味をなさないとしたら、それは私がビット/バイトのビット単位のシフトや 1 と 0 の操作に関係することについてほとんど知らないからです。
解決
本当にビットの文字列表現を作成したい (または作成する必要がある) 場合は、文字列を長さ 8 の部分文字列に分割できます (最後の部分文字列は必ずしも長さ 8 であるとは限らないことに注意してください)。
整数には文字列表現を解析するメソッドがあり、radix = 2 で呼び出すことで「0」と「1」のシーケンスを解析できます。
static int parseInt(String s, int radix)
文字列引数を、2 番目の引数で指定された基数の符号付き整数として解析します。
--
編集:コメントによると Byte.parseByte が進むべき道です。
他のヒント
以下は単純ですが、おそらく非効率的な実装です。
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class BitOutputStream extends FilterOutputStream {
private int bits = 0;
private int n = 0;
private long totalBits = 0;
public BitOutputStream(OutputStream out) {
super(out);
}
private void writeSingleBit(int bit) throws IOException {
bits = (bits << 1) | (bit & 1);
n++;
totalBits++;
if (n == 8) {
super.write(bits);
bits = 0;
n = 0;
}
}
/**
* Writes the <i>numberOfBits</i> lower bits of <i>bitsToWrite</i> to the
* output stream, starting with the most significant bit.
*/
public void writeBits(int bitsToWrite, int numberOfBits) throws IOException {
for (int i = numberOfBits - 1; i >= 0; i--) {
int bit = bitsToWrite >> i;
writeSingleBit(bit);
}
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; i++)
writeBits(b[off + i], 8);
}
@Override
public final void write(int b) throws IOException {
writeBits(b, 8);
}
@Override
public final void flush() throws IOException {
writeBits(0, (8 - n) & 0x07);
}
/**
* Returns the number of bits that have been written to this bitstream.
*/
public long getTotalBits() {
return totalBits;
}
}
対応する単体テストは次のとおりです。
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.junit.Test;
public class BitOutputStreamTest {
@Test
public void hello() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BitOutputStream bos = new BitOutputStream(baos);
bos.writeBits(0x00, 2);
bos.writeBits(0x01, 2);
bos.writeBits(0x02, 2);
bos.writeBits(0x02, 2);
bos.writeBits(0x03, 2);
assertEquals(10, bos.getTotalBits());
bos.close();
assertEquals(16, bos.getTotalBits());
assertArrayEquals(new byte[] { 0x1A, (byte) 0xC0 }, baos.toByteArray());
}
}
このコードは、必要な文字列表現のビットを出力しませんが、後でバイトベースのストリームにビットを書き込む場合は、これが適した方法です。
アップデート (2010-09-25): のバグを修正しました write(byte[], int, int)
方法。追加するのを忘れてしまいました off
配列のインデックスに。
なぜあなたは最初の「バイナリ文字列」に変換する必要がありますか?ただ、出力としてバイトを書くことに直進します。
は概念的に、あなたは何をすべきかあなたがbyte
をいっぱいにするまで、byte
に書き込みビットです。これは、ビットシフトで行われます。あなたのような何かをする価値の下部に1ビットを追加するには:
b = (b << 1) | 1;
あなたが行われるまで、別の余地を作るためにあなたの出力byte[]
を成長させる必要があるバイトを埋めた後、次にと。あなたは着実に出力ByteArrayOutputStream
に、あまりにもそのためbyte
を使用し、後でbyte[]
を得ることができます。
私は<のhref = "http://code.google.com/p/zxing/source/browse/trunk/core/src/com/google/zxing/common/BitArray.java" のrelであなたを指すことができます=「nofollowをnoreferrer」>あなたはビットを付加し、その後、結果として得られたバイトを取得することができますクラスのは、それがint
s代わりのバイト配列を作成していますと思いました。あなたは一例として、それを使用することができます。
。
あなたは Preon の代わりに見たいと思うかもしれません。 Preonは、最初にすべてのBitChannel抽象化を持っている自分自身をシフトについて多くを心配することから防止できます。あなたは、単にBitChannelにビットシーケンスを書くことができます。これは、内部的に「ビットポインタ」を追跡し、バイト、さらに下流にすべてを翻訳します。
BitChannel channel = new OutputStreamBitChannel(...);
channel.write(1, 0); // 0 = 'h'
channel.write(2, 1); // 01 = 'e'
channel.write(3, 2); // 10 = 'l'
channel.write(4, 2); // 11 = '0'
しかし、理想的に、あなたはすべてのの時にこの自分でのに対処することからあなたを妨げるPreonの高いレベルの抽象化(preon結合)を使用することができるだろう。それはちょうどあなたの文字列の注釈が必要になります。
@BoundHuffmanCoded String toBeEncoded = "hello";
...とPreonは残りの世話をするでしょう。さて、これは理想的なケースである、とPreonは、のまだのこの注釈を持っていない、覚えておいてください。しかし、この自分のためのコーデックを登録することが可能です。これは間違いなくPreonの将来のバージョンになります何かがあるため、しかしそれに目が離せないます。