为什么Java';s String.getBytes()使用;ISO-8859-1“;

为什么Java';s String.getBytes()使用;ISO-8859-1“;,java,utf-8,character-encoding,iso-8859-1,Java,Utf 8,Character Encoding,Iso 8859 1,从java.lang.StringCodeing: String csn = (charsetName == null) ? "ISO-8859-1" : charsetName; 这是在linux jdk 7中从Java.lang.getBytes()使用的 我总是觉得UTF-8是默认的字符集 谢谢这是出于兼容性原因 从历史上看,Windows和Unix上所有未指定字符集的java方法当时都使用通用的方法,即“ISO-8859-1” 正如Isaac和javadoc所提到的,使用默认的平台编码

从java.lang.StringCodeing:

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
这是在linux jdk 7中从Java.lang.getBytes()使用的 我总是觉得UTF-8是默认的字符集


谢谢

这是出于兼容性原因

从历史上看,Windows和Unix上所有未指定字符集的java方法当时都使用通用的方法,即
“ISO-8859-1”

正如Isaac和javadoc所提到的,使用默认的平台编码(请参阅):

执行字符串到字节或字节到字符串转换时,始终指定字符集。

即使像
String.getBytes()
一样,您仍然会发现一个未弃用的方法没有使用字符集(当Java 1.1出现时,大多数方法都已弃用)。就像endianness一样,平台格式是不相关的,相关的是存储格式的规范。

有点复杂。。。 Java尝试使用默认字符编码,使用String.getBytes()返回字节

  • 默认字符集由system file.encoding属性提供
  • 这是缓存的,在JVM启动后通过System.setProperty(..)更改它是没有用的
  • 如果file.encoding属性未映射到已知字符集,则指定UTF-8
。。。。这里是棘手的部分(可能永远不会起作用)

如果系统无法使用默认字符集(UTF-8或其他字符集)对字符串进行解码或编码,则将退回到ISO-8859-1。如果后备方案不起作用。。。系统将失败

。。。。真正地(喘息!)。。。如果我指定的字符集不能使用,并且UTF-8或ISO-8859-1也不能使用,它会崩溃吗

对。StringCodeing.encode(…)方法中的Java源注释状态:

//如果我们找不到ISO-8859-1(一种必需的编码),那么安装就会出现严重问题

。。。然后调用System.exit(1)


那么,为什么在getBytes()方法中有一个对ISO-8859-1的有意回退呢? 用户JVM可能不支持UTF-8或JVM启动时指定的字符集中的解码和编码,尽管可能性不大

那么,在getBytes()期间,字符串类中是否正确使用了默认字符集

不。不过,更好的问题是


String.getBytes()是否兑现了它的承诺? Javadoc中定义的合同是正确的

当此字符串无法在中编码时,此方法的行为 默认字符集未指定。
CharsetEncoder
类应为 当需要对编码过程进行更多控制时使用


好消息(以及更好的做事方式) 在将字节转换为字符串(反之亦然)时,建议始终明确指定“ISO-8859-1”或“US-ASCII”或“UTF-8”或任何您想要的字符集,除非您之前已获得默认字符集并100%确保它是您需要的字符集

请改用此方法:

public byte[] getBytes(String charsetName)
要查找系统的默认设置,只需使用:

Charset.defaultCharset()

希望有帮助。

无参数
String.getBytes()
方法默认情况下不使用ISO-8859-1。如果可以确定,它将使用默认的平台编码。但是,如果缺少或是无法识别的编码,它将作为“默认值”返回到ISO-8859-1

你应该很少在实践中看到这一点。通常,将正确检测平台默认编码


但是,我强烈建议您在每次执行编码或解码操作时指定显式字符编码。即使您想要平台默认值,也要明确指定。

详细说明双向飞碟的答案(这当然是正确的答案)

在的源代码中
getBytes()
调用
StringCoding.encode(char[]ca,int off,int len)
它的第一行有:

String csn = Charset.defaultCharset().name();

然后(不是立即而是绝对地)调用
static byte[]StringEncoder.encode(String charsetName,char[]ca,int off,int len)
您引用的行来自哪里-将csn作为charsetName传递-因此在这一行中,
charsetName
将成为默认的字符集(如果存在)。

不完全正确。在IBM的OS/390(后来命名为z/OS)上,文本文件用EBCDIC编码,而不是ASCII编码;因此,那里的默认平台编码不是ISO-8859-1,而是一些基于EBCDIC的编码(比如EBCDIC 0037)。如果不使用字符集的AIK方法也不被弃用,它们应该只使用默认字符集,不是吗?我知道这可能是一个“遗留”代码,这不是一个很难解决的错误吗?如果您遵循getBytes()的流程(没有提供聊天集),您将看到它正在尝试获取默认字符集,如果没有找到,将返回一个“UTF-8”但是从上面的代码可以看出,stringcodes中有一个不同的逻辑,默认为ISO-8859-1,如果没有提供,这是一个冲突。。。我知道您可以传递字符集,问题是为什么它不默认为utf-8,行为在javadoc中指定。我将修改我的答案,把它清楚地贴出来。它不是:)这是我的观点javadoc声明:“使用平台的默认字符集将这个字符串编码成一个字节序列,将结果存储到一个新的字节数组中。”这就是问题所在,有些情况下Java不会使用默认字符集。你有一个很好的观点。因为如果有一个默认字符集,那么它应该使用它进行转换。你,我的朋友,发现了一只虫子!也许删除你最后的评论吧DIt没有-请参见下面的答案编码很难预测-Centos 6和Centos 7以及Oracle JDK和Open JDK上的字符集不同-您永远不应该依赖默认字符集。我不明白为什么有人会期望UTF-8,即使它如此流行——我相信Java在内部使用UTF-16
String csn = Charset.defaultCharset().name();