我正在开发JPEG解码器(我处于Huffman阶段),并且想将BinaryString写入文件中。 例如,假设我们这样做了:
String huff = "00010010100010101000100100";
我试图将其转换为整数,将其除以8,然后保存为整数表示,因为我无法写位:
huff.split("(?<=\\G.{8})"))
int val = Integer.parseInt(str, 2);
out.write(val); //writes to a FileOutputStream
问题是,在我的示例中,如果我尝试保存“ 00010010” ,它将其转换为 18 (10010),并且我需要0。
最后,当我阅读时:
int enter;
String code = "";
while((enter =in.read())!=-1) {
code+=Integer.toBinaryString(enter);
}
我得到了:
Code = 10010
代替:
Code = 00010010
我也尝试将其转换为位集,然后转换为Byte [],但我遇到了同样的问题。
答案 0 :(得分:1)
您的示例是您拥有字符串"10010"
,并且您希望字符串"00010010"
。也就是说,您需要将该字符串用零左键填充。请注意,由于要在循环中加入对Integer.toBinaryString
的多次调用的结果,因此需要在连接之前将这些字符串左移到循环中。
while((enter = in.read()) != -1) {
String binary = Integer.toBinaryString(enter);
// left-pad to length 8
binary = ("00000000" + binary).substring(binary.length());
code += binary;
}
答案 1 :(得分:-2)
您可能想看看UTF-8算法,因为它确实可以满足您的要求。它存储大量数据,同时丢弃零,保留相关数据并对其进行编码以占用更少的磁盘空间。
适用于:Java 7+版本
import java.nio.charset.StandardCharsets;
import java.util.Formatter;
public class UTF8EncodeDecode {
public static byte[] utf8encode(int codepoint) {
return new String(new int[]{codepoint}, 0, 1).getBytes(StandardCharsets.UTF_8);
}
public static int utf8decode(byte[] bytes) {
return new String(bytes, StandardCharsets.UTF_8).codePointAt(0);
}
public static void main(String[] args) {
System.out.printf("%-7s %-43s %7s\t%s\t%7s%n",
"Char", "Name", "Unicode", "UTF-8 encoded", "Decoded");
for (int codepoint : new int[]{0x0041, 0x00F6, 0x0416, 0x20AC, 0x1D11E}) {
byte[] encoded = utf8encode(codepoint);
Formatter formatter = new Formatter();
for (byte b : encoded) {
formatter.format("%02X ", b);
}
String encodedHex = formatter.toString();
int decoded = utf8decode(encoded);
System.out.printf("%-7c %-43s U+%04X\t%-12s\tU+%04X%n",
codepoint, Character.getName(codepoint), codepoint, encodedHex, decoded);
}
}
}
https://rosettacode.org/wiki/UTF-8_encode_and_decode#Java
UTF-8是一种可变宽度的字符编码,它能够使用一到四个8位字节来编码Unicode中的所有1,112,064 [nb 1]个有效代码点。[nb 2]该编码是由Unicode标准定义的,最初由Ken Thompson和Rob Pike设计。[1] [2]该名称源自Unicode(或通用编码字符集)转换格式– 8位。[3]
它旨在与ASCII向后兼容。具有较低数值的代码点(通常会更频繁地出现)使用较少的字节进行编码。 Unicode的前128个字符(与ASCII一对一对应)使用与ASCII相同的二进制值的单个字节进行编码,因此有效的ASCII文本也是有效的UTF-8编码的Unicode。由于在将非ASCII代码点编码为UTF-8时不会出现ASCII字节,因此UTF-8可以安全地用于大多数以特殊方式解释某些ASCII字符的编程语言和文档语言,例如“ /”(斜杠)。文件名,转义序列中的“ \”(反斜杠)和printf中的“%”。
https://en.wikipedia.org/wiki/UTF-8
二进制数11110000 10010000 10001101 10001000
在UTF-8中变成F0 90 8D 88
。由于将其存储为文本,因此从必须存储32个字符到存储8个字符。由于它是众所周知的且设计合理的编码,因此可以轻松地将其反转。所有的数学运算都为您完成。
您的示例00010010100010101000100100
(或更确切地说00000001 0010100 0101010 00100100
)将转换为*$
(我的机器上两个不可打印的字符)。这就是二进制文件的UTF-8编码。我错误地使用了另一个站点,该站点使用的是我以十进制而不是二进制形式输入的数据。
https://onlineutf8tools.com/convert-binary-to-utf8
对于UTF-8以及如何将其应用于答案的很好的解释:
https://hackaday.com/2013/09/27/utf-8-the-most-elegant-hack/
编辑:
我将这个问题作为减少存储值所需的字符数量的一种方法,这是一种编码方式。 UTF-8是一种编码。 OP以“非标准”方式使用,可以使用UTF-8以更短的格式编码其0和1的字符串。这就是答案的相关性。
如果将字符连接起来,则可以轻松地从4x 8位(32位)变为8x 8位(64位),并编码高达9,223,372,036,854,775,807的值。