单个UTF-8字符到字节

时间:2015-04-02 19:16:51

标签: java

如果我将UTF-8 char转换为byte,那么基于语言环境,环境等的这3个实现的结果是否会有所不同?

byte a = "1".getBytes()[0];
byte b = "1".getBytes(Charset.forName("UTF-8"))[0];
byte c = '1';

2 个答案:

答案 0 :(得分:4)

您的第一行 依赖于环境,因为它会使用系统的默认字符编码对字符串进行编码,该编码可能是UTF-8,也可能不是。{/ p>

无论系统的区域设置或默认字符编码是什么,您的第二行始终会产生相同的结果。它将始终使用UTF-8对字符串进行编码。

请注意,UTF-8是一种可变长度的字符编码。只有前127个字符在一个字节中编码;所有其他字符将占用2到6个字节。

您的第三行将char投射到int。这将导致int包含字符的UTF-16字符代码,因为Java char使用UTF-16存储字符。由于UTF-16以与UTF-8相同的方式对字符进行部分编码,因此结果将与第二行相同,但对于任何字符通常都不是这样。

答案 1 :(得分:1)

原则上这个问题已经得到了回答,但我无法抗拒发布一些涂鸦,对于那些喜欢玩代码的人来说:

import java.nio.charset.Charset;

public class EncodingTest {

    private static void checkCharacterConversion(String c) {
        byte asUtf8 = c.getBytes(Charset.forName("UTF-8"))[0];
        byte asDefaultEncoding = c.getBytes()[0];
        byte directConversion = (byte)c.charAt(0);
        if (asUtf8 != asDefaultEncoding) {
            System.out.println(String.format(
                "First char of %s has different result in UTF-8 %d and default encoding %d",
                c, asUtf8, asDefaultEncoding));
        }
        if (asUtf8 != directConversion) {
            System.out.println(String.format(
                "First char of %s has different result in UTF-8 %d and direct as byte %d",
                c, asUtf8, directConversion));
        }
    }

    public static void main(String[] argv) {

       // btw: first time I ever wrote a for loop with a char - feels weird to me
       for (char c = '\0'; c <= '\u007f'; c++) {
           String cc = new String(new char[] {c});
           checkCharacterConversion(cc);
       }
    }
}

如果你这样做,例如用:

java -Dfile.encoding="UTF-16LE"  EncodingTest

你将得不到输出。 但是当然,如​​果你尝试的话,每个字节(好的,第一个除外)都是错的:

java -Dfile.encoding="UTF-16BE"  EncodingTest

因为&#34; big endian&#34;对于ascii字符,第一个字节始终为零。 这是因为在UTF-16中,ascii字符'\u00xy由两个字节表示,UTF16-LE表示为[xy, 0],UTF16-BE表示为[0, xy]

但是只有第一个语句产生任何输出,因此bc对于前127个ascii字符确实相同 - 因为在UTF-8中它们由单个字节编码。但是,对于任何其他角色来说,情况并非如此;它们都有UTF-8中的多字节表示。