为什么Java的String.getBytes()使用“ISO-8859-1”

时间:2012-09-30 07:12:09

标签: java utf-8 character-encoding iso-8859-1

来自java.lang.StringCoding:

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;

这是在linux jdk 7中从Java.lang.getBytes()中使用的内容 我一直认为UTF-8是默认的字符集吗?

谢谢

4 个答案:

答案 0 :(得分:35)

有点复杂......

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

  • 默认字符集由系统file.encoding属性提供。
  • 这是缓存的,在JVM启动后通过System.setProperty(..)更改它是没有用的。
  • 如果file.encoding属性未映射到已知的字符集,则指定了UTF-8。

....这是一个棘手的部分(可能永远不会发挥作用)....

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

....真的......(喘气!)......如果我的指定字符集无法使用,UTF-8或ISO-8859-1也无法使用,会崩溃吗?

是。 Java源代码在StringCoding.encode(...)方法中注释状态:

  

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

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


那么,为什么在getBytes()方法中有意回退到ISO-8859-1?

尽管不太可能,用户JVM可能不支持UTF-8中的解码和编码或JVM启动时指定的字符集。

然后,在getBytes()?

期间,String类中是否正确使用了默认字符集

没有。但是,更好的问题是......


String.getBytes()是否提供了它所承诺的内容?

Javadoc中定义的合同是正确的。

  

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


好消息(以及更好的做事方式)

始终建议明确指定“ISO-8859-1”或“US-ASCII”或“UTF-8”或将字节转换为字符串时所需的任何字符集 - 反之亦然 - 除非 - 您之前已经获得了默认字符集,并且100%确定它是您需要的字符集。

请改用此方法:

public byte[] getBytes(String charsetName)

要查找系统的默认设置,只需使用:

Charset.defaultCharset()

希望有所帮助。

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:5)

这是出于兼容性原因。

从历史上看,Windows和Unix上没有指定字符集的所有java方法当时都使用了常见的方法,即"ISO-8859-1"

正如Isaac和javadoc所提到的,使用了默认的平台编码(参见Charset.java):

594    public static Charset defaultCharset() {
595        if (defaultCharset == null) {
596            synchronized (Charset.class) {
597                String csn = AccessController.doPrivileged(
598                    new GetPropertyAction("file.encoding"));
599                Charset cs = lookup(csn);
600                if (cs != null)
601                    defaultCharset = cs;
602                else
603                    defaultCharset = forName("UTF-8");
604            }
605        }
606        return defaultCharset;
607    }

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

即使与String.getBytes()的情况一样,你仍然会发现一个未被弃用的方法没有使用charset(当Java 1.1出现时,大多数都被弃用了)。就像字节序一样,平台格式是无关紧要的,相关的是存储格式的规范。

答案 3 :(得分:1)

详细说明Skeet的答案(当然是正确答案)

java.lang.String的来源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) - 作为charsetName传递csn - 所以在这一行中charsetName 如果存在,则为默认字符集。