如果您有二进制字符串(字面意思是仅包含 1 和 0 的字符串对象),您将如何将它们作为位输出到文件中?
这是我正在研究的文本压缩器;它仍然困扰着我,最终让它工作会很好。谢谢!
如果您有二进制字符串(字面意思是仅包含 1 和 0 的字符串对象),您将如何将它们作为位输出到文件中?
这是我正在研究的文本压缩器;它仍然困扰着我,最终让它工作会很好。谢谢!
最简单的方法是简单地取 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 );
}
您需要进行一些调整,但这是一般的想法。
如果你幸运的话,java.math.BigInteger 可以为你做所有事情。
String s = "11001010001010101110101001001110";
byte[] bytes = (new java.math.BigInteger(s, 2)).toByteArray();
这确实取决于您想要的字节顺序(大端)和右对齐(如果位数不是 8 的倍数),但之后修改数组可能比自己进行字符转换更简单.
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);
}
假设 String 有 8 位的倍数,(否则您可以填充它),利用 Java 在 Integer.valueOf 方法中的内置解析来执行以下操作:
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
非常简单地将字节写入。
另一方面,如果您寻求效率,您应该考虑不使用字符串来存储开始的位,而是直接在压缩器中构建字节。