从编译到运行,Java String 编码究竟是如何工作的 [英] From compilation to runtime, how does Java String encoding really work

查看:20
本文介绍了从编译到运行,Java String 编码究竟是如何工作的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近意识到我并不完全了解 Java 的字符串编码过程.

I recently realized that I don't fully understand Java's string encoding process.

考虑以下代码:

public class Main
{
    public static void main(String[] args)
    {
        System.out.println(java.nio.charset.Charset.defaultCharset().name());
        System.out.println("ack char: ^"); /* where ^ = 0x06, the ack char */
    }
}

由于控制字符是 在 windows-1252 和 ISO-8859-1 之间的不同解释,我选择了 ack 字符进行测试.

Since the control characters are interpreted differently between windows-1252 and ISO-8859-1, I chose the ack char for testing.

我现在用不同的文件编码编译它,UTF-8,windows-1252, 和 ISO-8859-1.两者都编译为完全相同的东西,由 md5sum 验证.

I now compile it with different file encodings, UTF-8, windows-1252, and ISO-8859-1. The both compile to the exact same thing, byte-per-byte as verified by md5sum.

然后我运行程序:

$ java Main | hexdump -C
00000000  55 54 46 2d 38 0a 61 63  6b 20 63 68 61 72 3a 20  |UTF-8.ack char: |
00000010  06 0a                                             |..|
00000012

$ java -Dfile.encoding=iso-8859-1 Main | hexdump -C
00000000  49 53 4f 2d 38 38 35 39  2d 31 0a 61 63 6b 20 63  |ISO-8859-1.ack c|
00000010  68 61 72 3a 20 06 0a                              |har: ..|
00000017

$ java -Dfile.encoding=windows-1252 Main | hexdump -C
00000000  77 69 6e 64 6f 77 73 2d  31 32 35 32 0a 61 63 6b  |windows-1252.ack|
00000010  20 63 68 61 72 3a 20 06  0a                       | char: ..|
00000019

无论使用哪种编码,它都能正确输出0x06.

It correctly outputs the 0x06 no matter which encoding is being used.

好的,它仍然输出相同的 0x06,它会被 windows-1252 代码页解释为可打印的 [ACK] 字符.

Ok, it still outputs the same 0x06, which would be interpreted as the printable [ACK] char by windows-1252 codepages.

这就引出了几个问题:

  1. 正在编译的 Java 文件的代码页/字符集是否预期与编译它的系统的默认字符集相同?两者总是同义词吗?
  2. 编译后的表示似乎不依赖于编译时字符集,情况确实如此吗?
  3. 这是否意味着如果 Java 文件中的字符串不使用当前字符集/语言环境的标准字符,则它们在运行时可能会被不同地解释?
  4. 关于 Java 中的字符串和字符编码,我还应该了解什么?

推荐答案

  1. 源文件可以是任何编码
  2. 您需要告诉编译器源文件的编码(例如 javac -encoding...);否则,假定平台编码
  3. 在类文件二进制文件中,字符串文字存储为(修改后的)UTF-8,但除非您使用字节码,否则这无关紧要(请参阅 JVM 规范)
  4. Java 中的字符串始终为 UTF-16(参见 Java 语言规范)
  5. System.out PrintStream 会将您的字符串从 UTF-16 转换为系统编码中的字节,然后再将它们写入 stdout
  1. Source files can be in any encoding
  2. You need to tell the compiler the encoding of source files (e.g. javac -encoding...); otherwise, platform encoding is assumed
  3. In class file binaries, string literals are stored as (modified) UTF-8, but unless you work with bytecode, this doesn't matter (see JVM spec)
  4. Strings in Java are UTF-16, always (see Java language spec)
  5. The System.out PrintStream will transform your strings from UTF-16 to bytes in the system encoding prior to writing them to stdout

注意事项:

这篇关于从编译到运行,Java String 编码究竟是如何工作的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆