Java UTF-8编码产生错误的输出

use*_*258 2 java string encoding utf-8

在Java中,我一直在尝试使用UTF-8编码将String写入文件,稍后将由另一个用不同编程语言编写的程序读取.在这样做时,我注意到将String编码为字节数组时创建的字节似乎没有正确的字节值.

我将问题缩小到符号"£",这似乎在编码为UTF-8时产生不正确的字节

byte[] byteArray = "£".getBytes(Charset.forName("UTF-8"));

// Print out the Byte Array of the UTF-8 converted string
// Upcast byte values to print the bytes as unsigned
for (byte signedByte : byteArray) {
  System.out.print((signedByte & 0xFF) + " ");
} 
Run Code Online (Sandbox Code Playgroud)

这输出6个字节的十进制值:239 190 130 239 189 163,以十六进制表示:ef be 82 ef bd a3

http://www.utf8-chartable.de/但是说十六进制中"£"的值是:c2 a3,输出应该是:194 163

当编码为UTF-8时,其他字符串似乎产生正确的字节,所以我想知道为什么Java为"£"生成这6个字节,以及我应该如何通过使用UTF-8编码将字符串正确地转换为字节数组

我也试过了

OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8");
out.write("£");
out.close();
Run Code Online (Sandbox Code Playgroud)

但这产生了相同的6个字节

Jon*_*eet 5

我怀疑问题是你在Java代码中使用字符串文字,使用编辑器将其写入一个编码 - 但是你在编译时没有指定相同的编码.换句话说,我怀疑你的"£"字符串实际上根本不是单个符号.

这应该很容易验证.例如:

char[] chars = "£".toCharArray();
for (char c : chars) {
    System.out.println((int) c);
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,您可以使用Unicode转义序列使用纯ASCII表示来指定字符串:

String pound = "\u00a3";
// Now encode as before
Run Code Online (Sandbox Code Playgroud)

我相信你会得到正确的字节.例如:

import java.nio.charset.Charset;

class Test {
    public static void main(String[] args) throws Exception {
        String pound = "\u00a3";
        byte[] bytes = pound.getBytes(Charset.forName("UTF-8"));
        for (byte b : bytes) {
            System.out.println(b & 0xff); // 194, 163
        }
    }
}
Run Code Online (Sandbox Code Playgroud)