如何从二进制文件读取由0和1组成的字符串序列?
解决Huffman编码二进制字符串的读取问题
首先,咱们先理清你当前的问题:你把Huffman生成的0/1二进制序列以字符串形式写入了二进制文件,但用DataInputStream读取时找不到直接的readString方法。其实关键是看你写入时用了什么方法,对应就能找到读取的方式,另外我也会给你更高效的位存储方案(毕竟存字符串太浪费空间了)。
一、针对你当前写入方式的读取方案
情况1:写入时用了DataOutputStream.writeUTF()
如果你的写入代码是类似这样的:
String huffmanBinary = "101001101..."; // 你的Huffman二进制字符串 try (FileOutputStream fos = new FileOutputStream("huffman.bin"); DataOutputStream dos = new DataOutputStream(fos)) { dos.writeUTF(huffmanBinary); // 用writeUTF写入字符串 } catch (IOException e) { e.printStackTrace(); }
那读取非常简单,DataInputStream刚好有对应的readUTF()方法,能直接还原你写入的字符串:
try (FileInputStream fis = new FileInputStream("huffman.bin"); DataInputStream dis = new DataInputStream(fis)) { String binaryString = dis.readUTF(); // 现在binaryString就是你之前写入的0/1序列了 System.out.println("读取到的二进制序列:" + binaryString); } catch (IOException e) { e.printStackTrace(); }
情况2:写入时直接用了getBytes()转字节写入
如果你的写入代码是把字符串转成字节数组写入的:
dos.write(huffmanBinary.getBytes(StandardCharsets.UTF_8));
那读取时需要先把文件里的所有字节读出来,再转成字符串,注意要和写入时用的编码一致:
try (FileInputStream fis = new FileInputStream("huffman.bin"); DataInputStream dis = new DataInputStream(fis); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int len; while ((len = dis.read(buffer)) != -1) { baos.write(buffer, 0, len); } String binaryString = new String(baos.toByteArray(), StandardCharsets.UTF_8); System.out.println("读取到的二进制序列:" + binaryString); } catch (IOException e) { e.printStackTrace(); }
二、更高效的Huffman存储方案(推荐)
其实把0/1序列存成字符串是很浪费空间的——每个字符占1字节,而实际每个0/1只需要1bit。比如1000位的序列,存字符串要1000字节,而用位存储只需要125字节,这才符合Huffman编码压缩的初衷。
写入时:把二进制序列转成字节存储
我们可以把每8位二进制转成一个字节,不足8位的补0(还要记录补了多少位,方便读取时还原):
String binaryString = "10100110101"; // 示例Huffman序列 int padding = 8 - (binaryString.length() % 8); if (padding != 8) { // 补0到8的倍数 binaryString += "0".repeat(padding); } // 把8位一组转成字节 byte[] bytes = new byte[binaryString.length() / 8]; for (int i = 0; i < bytes.length; i++) { String byteStr = binaryString.substring(i*8, (i+1)*8); bytes[i] = (byte) Integer.parseInt(byteStr, 2); } // 写入文件:先写补位数量,再写字节数组 try (FileOutputStream fos = new FileOutputStream("huffman_opt.bin"); DataOutputStream dos = new DataOutputStream(fos)) { dos.writeInt(padding); // 记录补了多少个0 dos.write(bytes); } catch (IOException e) { e.printStackTrace(); }
读取时:把字节转回二进制序列
读取时先拿到补位数量,再把每个字节转成8位二进制字符串,最后去掉补的0:
try (FileInputStream fis = new FileInputStream("huffman_opt.bin"); DataInputStream dis = new DataInputStream(fis)) { int padding = dis.readInt(); byte[] bytes = new byte[fis.available()]; dis.readFully(bytes); StringBuilder binaryBuilder = new StringBuilder(); for (byte b : bytes) { // 把字节转成8位二进制,不足前面补0(注意要&0xFF避免负数问题) String byteStr = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'); binaryBuilder.append(byteStr); } // 去掉补的0,还原原始序列 if (padding != 8) { binaryBuilder.setLength(binaryBuilder.length() - padding); } String binaryString = binaryBuilder.toString(); System.out.println("还原的二进制序列:" + binaryString); } catch (IOException e) { e.printStackTrace(); }
这样既节省了存储空间,也更符合Huffman编码的设计逻辑~
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

