String s = new String(s.getBytes("UTF-8"),"UTF-8"); 和 String s = new String(s.getBytes(),"UTF-8"); 有什么区别?

3
什么是“difference between”?
String(s.getBytes("UTF-8"),"UTF-8"); 

并且

String(s.getBytes(),"UTF-8");

在第一个代码示例中,一些特殊字符被解码了,为什么?有什么区别?

如果我使用UTF-8进行双重解码,会对任何内容产生影响吗?


7
s.getBytes() 使用的是你的 JVM 默认的语言环境。因此,区别取决于字符串的内容和默认的语言环境,有可能没有任何区别。 - Andy Turner
6
建议退一步思考:你在这里试图达到什么目的? - Jon Skeet
2
尽量避免使用代码s.getBytes(),特别是当你处理不能适应ASCII代码边界的字符时,例如阿拉伯语、中文、印地语等。s.getBytes()将使用平台的默认编码,而我建议您始终使用最智能和紧凑的Unicode编码UTF-8 - Pushpesh Kumar Rajwanshi
3
“UTF-8编码字符串”并不存在,一个字符串就是一个字符串。如果你有一个字节数组,使用new String(bytes, Charsets.UTF_8)将其转换为字符串才有意义。请在问题中提供更多关于你所拥有的数据以及如何接收它的信息。 - Jon Skeet
1
@JalaSureshreddy:补充Jon Skeet所说的:如果s是一个String,那就意味着它已经被解码了。如果由于不正确的解码而包含?字符,则现在修复这些字符为时已晚:无论你对字符串进行多少次编码和解码,都无法恢复最初的字符串。你需要找到第一次解码该字符串的位置,并在那里使用正确的字符集。 - Daniel Pryden
显示剩余4条评论
3个回答

5
javadoc中得知:
对于getBytes()方法:
将此字符串使用平台的默认字符集编码为一系列字节,将结果存储到新的字节数组中。
getBytes(Charset)方法则表示:
使用给定的字符集将此字符串编码为一系列字节,将结果存储到新的字节数组中。
因此,第二个版本允许您完全控制,而第一个调用则依赖于平台默认字符集。
就是这样简单。
有关“平台默认字符集”,请参见此处。请注意,人们正在要求在各个领域都将默认值设为UTF-8(请参见此处)。

我的平台默认也是UTF-8,但是String(s.getBytes(),"UTF-8")无法解码一些特殊字符,但是通过String(s.getBytes("UTF-8"),"UTF-8")可以解码,为什么会这样呢? - Jala Sureshreddy
1
那么您可能应该提出一个新问题,并提供一个精确的 [mcve],以展示您的问题;-) - GhostCat

3

所以,你在询问这两行:

String s1 = new String(s.getBytes("UTF-8"), "UTF-8"); // line 1
String s2 = new String(s.getBytes(), "UTF-8"); // line 2

这两行代码都没有实际作用。第二行甚至比第一行更糟糕;根据系统的默认字符编码,它可能不仅无用,而且是错误的。
第一行实际上什么也没做。它使用UTF-8字符编码将字符串s编码为字节,然后立即使用UTF-8解码字节回到字符串。字符串s1始终包含与原始字符串完全相同的内容;编码和解码是无用的。
第二行的作用取决于您的系统上使用的默认字符编码。如果默认字符编码是UTF-8,则它与第一行完全相同。如果它与UTF-8不同,则会得到一个解码不正确的字符串。
假设您的系统的默认字符编码是ISO-8859-1。那么第二行使用ISO-8859-1对字符串进行编码,然后立即将结果解码为UTF-8——这是错误的。您可能会得到具有解码不正确字符甚至异常的字符串。
阅读您正在使用的方法的API文档以了解它们的确切功能:

1
你在问题中提供的两个例子是无意义的。
Java中的String以UTF-16代码点数组的形式存储在内存中。 如果在将该数组转换为String之后再将byte[]识别为UTF-8代码点数组,则为时已晚。
如果你收到一个byte[]并想将其存储为String, 那么这样做是有意义的:
//assume input byte[] kapow
String blammy = new String(kapow, StandardCharsets.UTF_8);

如果您有一个字符串值并希望将其作为UTF-8编码的字节数组写入某个位置,那么这是有意义的。
// assume input String blammy 
byte[] kapow = blammy.getBytes(StandardCharsets.UTF_8);

请注意,在这两种情况下,我都使用了(blah,Charset)方法版本。 这样做。 (blah,“UTF-8”)版本会抛出一个已检查的异常。 (blah,Charset)版本从不引发异常,StandardCharsets类执行此操作(来自StandardCharsets JavaDoc页面): 常量定义用于标准字符集。这些字符集保证在Java平台的每个实现中都可用。

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