Java中的位操作与输出

Java中的位操作与输出,java,bit-manipulation,Java,Bit Manipulation,如果您有二进制字符串(字面上的字符串对象只包含1和0),如何将它们作为位输出到文件中 这是一个文本压缩机,我正在工作;它仍然困扰着我,如果能最终让它工作起来那就太好了。谢谢 最简单的方法是简单地获取8个连续字符,将它们转换为一个字节并输出该字节。如果可以识别流的结尾,请在结尾处填充零,或者在文件开头添加长度(以位为单位)的头 内部循环看起来像: 字节[]缓冲区=新字节[(string.length+7)/8]; 对于(int i=0;i=0;--j) if(字符串[i*8+j]=='1') 当

如果您有二进制字符串(字面上的字符串对象只包含1和0),如何将它们作为位输出到文件中


这是一个文本压缩机,我正在工作;它仍然困扰着我,如果能最终让它工作起来那就太好了。谢谢

最简单的方法是简单地获取8个连续字符,将它们转换为一个字节并输出该字节。如果可以识别流的结尾,请在结尾处填充零,或者在文件开头添加长度(以位为单位)的头

内部循环看起来像:


字节[]缓冲区=新字节[(string.length+7)/8];
对于(int i=0;i=0;--j)
if(字符串[i*8+j]=='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);
}
String s=“1100101000010101110101001001110”;
字节[]数据=新字节[s.length()/8];
对于(int i=0;i
然后,您应该能够非常简单地将字节写入
FileOutputStream


另一方面,如果你寻找效率,你应该考虑不使用一个字符串来开始存储这些比特,但是直接在你的压缩器中建立字节。

如果你幸运,java. Math.BigType可以为你做任何事情。
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;
        }
    }
}
String s = "11001010001010101110101001001110";
byte[] bytes = (new java.math.BigInteger(s, 2)).toByteArray();

这取决于字节顺序(大端)和右对齐(如果位数不是8的倍数)这是您想要的,但以后修改数组可能比自己进行字符转换更简单。

我很好奇——0和1是如何以字符串形式结束的,而不是以字节数组或其他更合适的数据类型结束的?这是因为我递归地将“0”和“1”字符从我的Huffman TreeThis添加到Stringbuffer中的olution使用字符数组而不是字符串对象,但它很容易修改。我认为Java字符有2个字节宽?如果前导字节是UTF8前缀字符,它们可以是。这有什么关系?从字符串中提取字符并与其他字符进行比较,而不进行任何转换或解码。构造函数bigineger(字符串)接受一个以10为基数的参数。它应该是新的BigInteger(s,2)危险!此解决方案永远不会在输出字节数组中产生前导零,即使它们属于。BigInteger会更好。如果他将位存储在文件中,它可能大于32。BigInteger将无法正确处理前导零,并且此方法在超过32位的情况下工作正常。它在一个类型中解析8。顺便说一句,如果
s
由于在分配字节数组时使用整数除法,因此少于8个字符。这就是为什么答案以“假设字符串具有8位的倍数”开头的原因。
if (nextChar == '0')
{
    bos.writeBits(0, 1);
}
else
{
    bos.writeBits(1, 1);
}
String s = "11001010001010101110101001001110";
byte[] bytes = (new java.math.BigInteger(s, 2)).toByteArray();