使用二进制编码将byte[]转换为字符串

4
我希望将byte[]中的每个byte转换为char,并将这些字符放在一个字符串中。这就是一些数据库所谓的“二进制”编码。到目前为止,我找到的最好的方法是使用庞大的样板代码:
byte[] bytes = ...;
char[] chars = new char[bytes.length];
for (int i = 0; i < bytes.length; ++i) {
    chars[i] = (char) (bytes[i] & 0xFF);
}
String s = new String(chars);

有没有来自Java SE或者Apache Commons的其他选项?我希望能有像这样的东西:
final Charset BINARY_CS = Charset.forName("BINARY");
String s = new String(bytes, BINARY_CS);

但我不想编写字符集及其编解码器(至少目前还不想)。JRE或Apache Commons中是否有现成的二进制字符集可用?


1
那个“巨大的样板文件”怎么了?只需将其包装在一个接受字节数组并返回字符串的方法中即可。 - ColinD
2
不太确定你的问题。 ISO 8859-1(Latin-1)不能胜任吗?它是一个8位单字节编码... - Dunes
@ColinD 那个包装已经做过了。但是我在不同的项目中多次编写了这个方法,它们之间没有共享库。我不想为此构建一个库。这就是为什么我们使用诸如java.util、java.text、java.lang和Apache Commons之类的东西。 - fernacolo
4个回答

9
您可以使用ASCII编码来处理7位字符。
String s = "Hello World!";
byte[] b = s.getBytes("ASCII");
System.out.println(new String(b, "ASCII"));

或者8位ASCII码

String s = "Hello World! \u00ff";
byte[] b = s.getBytes("ISO-8859-1");
System.out.println(new String(b, "ISO-8859-1"));

编辑

System.out.println("ASCII => " + Charset.forName("ASCII"));
System.out.println("US-ASCII => " + Charset.forName("US-ASCII"));
System.out.println("ISO-8859-1 => " + Charset.forName("ISO-8859-1"));

打印

ASCII => US-ASCII
US-ASCII => US-ASCII
ISO-8859-1 => ISO-8859-1

US-ASCIIASCII 的别名。 - Peter Lawrey
1
相反,"ASCII" 是 "US-ASCII" 的别名。显然,两者都可以使用,我只是说这是 Java 使用的“官方”名称。 - jtahlborn
1
@Peter Lawrey:从您提供的文章中可以看到:“US-ASCII是互联网数字分配机构(IANA)对ASCII的首选字符集名称。”此外,我相信在所有Java实现中必须存在的字符集是“US-ASCII”。 - ColinD
1
ISO-8859-1起了作用。非常有趣。我以为它会将一些字节映射到0x7F,因为并不是所有的字节值在这种编码中都有意义(根据http://en.wikipedia.org/wiki/ISO/IEC_8859-1)。 - fernacolo
1
标准字符集标识符列在 Charset Javadoc 中:http://docs.oracle.com/javase/6/docs/api/java/nio/charset/Charset.html - ColinD
显示剩余8条评论

1

你可以跳过使用字符数组和转化为字符串的步骤,直接使用StringBuilder(如果你担心多线程问题,也可以使用StringBuffer)。我的示例展示了如何使用StringBuilder。

byte[] bytes = ...;
StringBuilder sb = new StringBuilder(bytes.length);
for (int i = 0; i < bytes.length; i++) {
  sb.append((char) (bytes[i] & 0xFF));
}

return sb.toString();

我知道这不是你其他问题的答案,只是想帮忙简化“样板”代码。


1
如果你像在你的例子中一样将其用作本地变量,那么没有不使用StringBuilder而使用StringBuffer的好理由。 - ColinD
@ColinD 已修改为 StringBuilder。你说得对。以前在 Java 5 之前,我们只能使用 StringBuffer。此外,我们有一个多线程应用程序,所以 StringBuffer 对我们很有效。但是,我同意你的观点。 - Chris Aldrich

0

0

有一个字符串构造函数,它接受一个字节数组和一个指定字节格式的字符串:

String s = new String(bytes, "UTF-8");   // if the charset is UTF-8
String s = new String(bytes, "ASCII");   // if the charset is ASCII

1
UTF-8 会将一些多字节字符转换为单个字符,因此它不能正常工作。ASCII 只处理 7 位字符,因此存在一些无法处理的 7 位字符。 - fernacolo
为什么被踩呢?我告诉你,String构造函数会完全做出你想要的事情。抱歉没有为你做好使用哪种字符集的研究... - Andrew Rasmussen
这个踩并不是我点的。顺便说一下,感谢你的回答尝试。 - fernacolo

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