将由0和1组成的字符串以比特形式存储为文件

4
我正在开发一款Huffman Java应用程序,离完成就差最后一步了。但是我有一个问题,需要将类似于“101011101010”这样的字符串保存到文件中。当我使用当前代码保存它时,它会被保存为字符,每个0或1占用1个字节。我相信可以将每个0/1保存为位(bit)。我已经尝试使用BitSet和Integer.valueOf,但无法使它们正常工作。以下是我的当前代码:
FileOutputStream fos = new FileOutputStream("encoded.bin");
fos.write(encoded.getBytes());
fos.close();

当'encoded'是类似于"0101011101"的字符串时,如果我尝试将其保存为整数,则会删除前导0。

提前感谢!

编辑:哈夫曼是一种压缩方法,因此输出的文件应该尽可能小。


你为什么想要将字符串转换为整数?如果没有前导0的字符串可以保存,那么不能保存带有前导0的字符串吗?你的问题到底是什么? - Patrick
这是一种压缩方法。因此,一个'a'或'b'会被转换为类似于0110的内容(它是4位而不是1个字节)。问题在于我将1和0保存为1个字节,因此没有压缩(现在甚至更糟)。 - Luud van Keulen
3个回答

3

我想我找到了答案。我使用以下代码将1和0放入BitSet中:

BitSet bitSet = new BitSet(encoded.length());
int bitcounter = 0;
for(Character c : encoded.toCharArray()) {
    if(c.equals('1')) {
        bitSet.set(bitcounter);
    }
    bitcounter++;
}

接下来,我使用bitSet.toByteArray()将其保存到文件中。当我想再次读取它时,我使用BitSet.valueOf(bitSet.toByteArray())将其转换回位集。然后我像这样循环遍历位集:

String binaryString = "";
for(int i = 0; i <= set.length(); i++) {
    if(set.get(i)) {
        binaryString += "1";
    } else {
        binaryString += "0";
    }
}

感谢所有帮助过我的人。

0

二进制文件仅限于以八位的倍数存储位。您可以通过将字符串切成八位块,使用Byte.parseByte(eightCharString, 2)将它们转换为字节并将它们添加到字节数组中来解决此问题:

  • 通过将您的位字符串长度除以8来计算字节数组的长度
  • 分配所需长度的字节数组
  • 运行循环,从表示八的倍数的位置处获取字符串的子字符串
  • 解析每个块,并将结果放入相应的字节中
  • 在字节数组上调用fos.write()

我卡在了“解析每个块,并将结果放入相应的字节”的步骤。我不能使用Integer.parseInt,因为它会删除前导0。当我尝试使用Byte.parseByte(s, 2)时,它不起作用,因为它不是有符号的。 - Luud van Keulen
@LuudvanKeulen 你得到了什么异常?顺便说一下,如果解析int正常工作,你也可以将int结果转换为byte,它也会起作用。 - Sergey Kalinichenko
java.lang.NumberFormatException: 值超出范围。值:“11101101” 基数:10。我了解到这是因为它不接受高于某个值的任何内容,因此1111111是不可能的。 - Luud van Keulen
@LuudvanKeulen 在答案中我建议的方式中传递基数2 - Sergey Kalinichenko
将整数转换后,它应该可以工作。将基数设为2。 - Sergey Kalinichenko
显示剩余2条评论

0

试试这个。

String encoded = "0101011101";
FileOutputStream fos = new FileOutputStream("encoded.bin");
String s = encoded + "00000000".substring(encoded.length() % 8);
for (int i = 0, len = s.length(); i < len; i += 8)
    fos.write((byte)Integer.parseInt(s.substring(i, i + 8), 2));
fos.close();

如果我没记错的话,这会得到二进制字符串的十进制值,对吧?当我保存它时它是有效的,但是当我尝试读取它时,它会删除所有前导零。例如:我执行 Integer.parseInt("00001111", 2),它将返回15。当我尝试执行 Integer.toBinaryString(15) 时,它将返回1111。 - Luud van Keulen
你应该这样做:String s = "00000000" + Integer.toBinaryString(15); 然后 String decoded = s.substring(s.length() - 8); - user4910279

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接