Java InputStream encoding/charset

2022-09-03 17:40:34

运行以下(示例)代码

import java.io.*;

public class test {
    public static void main(String[] args) throws Exception {
        byte[] buf = {-27};
        InputStream is = new ByteArrayInputStream(buf);
        BufferedReader r = new BufferedReader(
                new InputStreamReader(is, "ISO-8859-1"));
        String s = r.readLine();
        System.out.println("test.java:9 [byte] (char)" + (char)s.getBytes()[0] + 
                " (int)" + (int)s.getBytes()[0]);
        System.out.println("test.java:10 [char] (char)" + (char)s.charAt(0) + 
                " (int)" + (int)s.charAt(0));
        System.out.println("test.java:11 string below");
        System.out.println(s);
        System.out.println("test.java:13 string above");
    }
}

给我这个输出

test.java:9 [byte] (char)? (int)63
test.java:10 [char] (char)? (int)229
test.java:11 string below
?
test.java:13 string above

如何在第 9 行打印输出中保留正确的字节值 (-27)?因此接收命令 (å) 的预期输出。System.out.println(s)


答案 1

如果要保留字节值,理想情况下,根本不使用 Reader。若要在文本中表示任意二进制数据,并在以后将其转换回二进制数据,应使用 base16 或 base64 编码。

但是,为了解释发生了什么,当您调用它时使用默认字符编码,该编码显然不包括Unicode字符U + 00E5。s.getBytes()

如果你到处打电话,而不是我怀疑你会得到正确的字节值......但是依靠ISO-8859-1这有点肮脏的IMO。s.getBytes("ISO-8859-1")s.getBytes()


答案 2

如前所述,(无参数)使用 Java 平台缺省编码,可能不是 ISO-8859-1。只需打印它应该可以工作,前提是您的终端和默认编码匹配并支持该字符。例如,在我的系统上,终端和默认的Java编码都是UTF-8。您看到“?”的事实表明您的不匹配或å不受支持。getBytes()

如果要在系统上手动编码为 UTF-8,请执行以下操作:

String s = r.readLine();
byte[] utf8Bytes = s.getBytes("UTF-8");

它应该给出一个带有 的字节数组。{-61, -91}


推荐