将字节数组转换为字符串(Java)
Posted
技术标签:
【中文标题】将字节数组转换为字符串(Java)【英文标题】:Converting byte array to String (Java) 【发布时间】:2011-08-06 02:16:49 【问题描述】:我正在 Google 应用引擎中编写一个网络应用程序。它允许人们基本上编辑在 blobstore 中存储为 .html
文件的 html 代码。
我正在使用 fetchData 返回文件中所有字符的byte[]
。我正在尝试打印到 html 以便用户编辑 html 代码。一切都很好!
这是我现在唯一的问题:
字节数组在转换回字符串时出现一些问题。智能引号和几个字符看起来很时髦。 (?的或日文符号等)具体来说,我看到的几个字节具有导致问题的负值。
智能引号在字节数组中返回为-108
和-109
。为什么会这样?如何解码负字节以显示正确的字符编码?
【问题讨论】:
重复***.com/questions/1536054/… 嗨,我知道这是一篇很老的帖子,但我也面临着类似的问题。我正在为 ssl 做一个中间人代理。我面临的问题和你的一样。我监听套接字并将数据输入InputStream
,然后输入byte[]
。现在,当我尝试将byte[]
转换为字符串(我需要使用响应体进行攻击)时,我得到了非常有趣的字符,其中充满了智能引号和问号等等。我相信你的问题和我的一样,因为我们都在处理byte[]
中的html
。可以请教吗?
顺便说一句,我用 Sytem.properties 找到了我系统的编码,发现它是“Cp1252”。现在,我使用了String str=new String(buffer, "Cp1252");
,但没有任何帮助。
What is character encoding and why should I bother with it的可能重复
【参考方案1】:
字节数组包含特殊编码的字符(您应该知道)。转成String的方法是:
String decoded = new String(bytes, "UTF-8"); // example for one encoding type
顺便说一下 - 出现的原始字节可能显示为负小数,因为 java 数据类型 byte
是有符号的,它涵盖了从 -128 到 127 的范围。
-109 = 0x93: Control Code "Set Transmit State"
值 (-109) 是 UNICODE 中不可打印的控制字符。所以 UTF-8 不是该字符流的正确编码。
“Windows-1252”中的0x93
是您正在寻找的“智能引用”,因此该编码的Java 名称是“Cp1252”。下一行提供了一个测试代码:
System.out.println(new String(new byte[]-109, "Cp1252"));
【讨论】:
我尝试使用 UTF-8,但它仍然显示为 ?'s。为什么没有找到那些负值的映射? 0x93 在 UTF-8 中是一个有效的连续字节,但是 - 如果它没有出现在设置了前两位的字节之后,那么该字节的存在只会排除它是 UTF-8。 @Josh Andreas 解释了原因 - 因为 Java 的byte
数据类型已签名。 “负”值只是具有最高有效字节集的字节。他还解释了您应该使用的最可能的字符集是 Windows-1252。不过,您应该从上下文或约定中知道要使用什么字符集,而不必猜测。【参考方案2】:
Java 7 及以上版本
您还可以将所需的编码作为来自StandardCharsets 的Charset
常量传递给String
构造函数。正如其他答案中所建议的那样,这可能比将编码作为String
传递更安全。
例如,对于 UTF-8 编码
String bytesAsString = new String(bytes, StandardCharsets.UTF_8);
【讨论】:
这是 2011 年答案的重复。-1 @james.garriss 我不认为是这样,因为我只是提到了 java 7 中引入的一个新构造函数,它允许将编码作为常量传递,我认为这更好,并且比之前的答案中提到的以前的 api 更安全,其中编码作为字符串传递,如果有的话。【参考方案3】:你可以试试这个。
String s = new String(bytearray);
【讨论】:
您可以尝试...但几乎在所有情况下都会失败。【参考方案4】:public class Main
/**
* Example method for converting a byte to a String.
*/
public void convertByteToString()
byte b = 65;
//Using the static toString method of the Byte class
System.out.println(Byte.toString(b));
//Using simple concatenation with an empty String
System.out.println(b + "");
//Creating a byte array and passing it to the String constructor
System.out.println(new String(new byte[] b));
/**
* @param args the command line arguments
*/
public static void main(String[] args)
new Main().convertByteToString();
输出
65
65
A
【讨论】:
【参考方案5】:public static String readFile(String fn) throws IOException
File f = new File(fn);
byte[] buffer = new byte[(int)f.length()];
FileInputStream is = new FileInputStream(fn);
is.read(buffer);
is.close();
return new String(buffer, "UTF-8"); // use desired encoding
【讨论】:
如果read
抛出异常,此代码将泄漏资源。【参考方案6】:
我建议Arrays.toString(byte_array);
这取决于你的目的。例如,我想保存一个字节数组,就像您在调试时可以看到的格式一样:[1, 2, 3]
如果您想保存完全相同的值而不将字节转换为字符格式,Arrays.toString (byte_array)
可以这,。但是如果你想保存字符而不是字节,你应该使用String s = new String(byte_array)
。在这种情况下,s
等价于字符格式的[1, 2, 3]
。
【讨论】:
您能否提供更多信息,说明您为什么建议这样做? (能解决问题吗?能说一下为什么能解决吗?)谢谢! 这取决于你的目的。例如,我想保存一个字节数组,就像您在调试时可以看到的格式一样: [1, 2, 3] 如果您想保存完全相同的值而不将字节转换为字符格式, Arrays.toString (byte_array) 就是这样做的。但是如果你想保存字符而不是字节,你应该使用 String s = new String(byte_array)。在这种情况下,s 等价于字符格式的 [1, 2, 3]。 @sas,您应该将此信息添加到您的答案本身(通过编辑它)而不是作为评论。通常在 SO 上,您应该始终牢记 cmets 可能随时被删除 - 真正重要的信息应该在答案本身中。【参考方案7】:Andreas_D 之前的回答很好。我只是要补充一点,无论你在哪里显示输出,都会有一个字体和一个字符编码,它可能不支持某些字符。
要确定是 Java 还是您的显示器有问题,请执行以下操作:
for(int i=0;i<str.length();i++)
char ch = str.charAt(i);
System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
Java 会将它无法理解的任何字符映射到 0xfffd 未知字符的官方字符。如果你看到一个“?”在输出中,但它没有映射到 0xfffd,这是您的显示字体或编码问题,而不是 Java。
【讨论】:
以上是关于将字节数组转换为字符串(Java)的主要内容,如果未能解决你的问题,请参考以下文章