Java中的Char编码

时间:2018-08-03 10:59:51

标签: java utf-8

我用记事本打开文件,在其中写上:“±”保存并关闭。

我尝试以两种方式读取此文件

第一:

        InputStream inputStream = Files.newInputStream(Paths.get("file.txt"));
        int result = inputStream.read();
        System.out.println(result);
        System.out.println((char) result);
  

196   Ä

第二:

        InputStream inputStream = Files.newInputStream(Paths.get("file.txt"));
        Reader reader = new InputStreamReader(inputStream);
        int result = reader.read();
        System.out.println(result);
        System.out.println((char) result);
  

261   ±

问题: 1)在二进制模式下,该字母是否另存为196?为什么不为261? 2)该字母另存为196,采用哪种编码?

我试图理解为什么存在差异

4 个答案:

答案 0 :(得分:4)

UTF-8将范围U+0080-U+07FF中的值编码为两个字节,格式为110xxxxx 10xxxxxx(更多信息位于wiki)。因此,只有xxxxx xxxxxx 11个字节可用于值。

ąindexed as U+0105,其中0105是十六进制值(十进制是261)。作为二进制,可以表示为

      01       05    (hex)
00000001 00000101    (bin)
     xxx xxxxxxxx <- values for U+0080 - U+07FF range encode only those bits

     001 00000101 <- which means `x` will be replaced by only this part 

因此,UTF-8编码将添加110xxxxx 10xxxxxx掩码,这意味着它将合并

110xxxxx 10xxxxxx
   00100   000101

变成(两个字节):

11000100 10000101

现在,InputStream将数据读取为原始字节。因此,当您第一次致电inputStream.read();时,您会得到11000100(十进制为196)。第二次调用inputStream.read();会返回10000101,十进制为133

Reader是Java 1.1中引入的软件,因此我们可以避免在代码中出现这种混乱情况。相反,我们可以指定Reader应该使用哪种编码方式(或让其使用默认编码方式)来获取正确编码的值,例如本例中的00000001 00000101(不带掩码)等于十六进制形式的0105和{{ 1}}的十进制形式。


简而言之

  • 如果要以文本形式读取数据,请使用261(采用正确指定的编码)
  • 如果要将数据读取为原始字节,请使用Reader

答案 1 :(得分:1)

由于您以不同的编码方式阅读了这两个字母,因此可以通过InputStreamReader::getEncoding检查编码。

String s = "ą";

char iso_8859_1 = new String(s.getBytes(), "iso-8859-1").charAt(0);
char utf_8 = new String(s.getBytes(), "utf-8").charAt(0);   

System.out.println((int) iso_8859_1 + " " + iso_8859_1);
System.out.println((int) utf_8 + " " + utf_8);

输出为

196 Ä
261 ą

答案 2 :(得分:0)

您获得decimal个字母的LATIN值 您需要save的{​​{1}}使用file编码标准。

请确保在阅读时使用类似的标准。

  

0x0105 261带OGONEK±的拉丁文小写字母A

     

0x00C4 196带有首字母缩略词的拉丁文大写字母

请参阅:-https://www.ssec.wisc.edu/~tomw/java/unicode.html

答案 3 :(得分:0)

尝试使用具有UTF-8编码的printf("Test : %c\n\n", a); ,该编码与用于从Notepad ++写入文件的编码相匹配:

InputStreamReader

对于您为什么看到看到的输出,我没有确切/可重复的答案,但是,如果您使用错误的编码阅读,则不一定会看到保存的内容。例如,如果单个字符// this will use UTF-8 encoding by default BufferedReader in = Files.newBufferedReader(Paths.get("file.txt")); String str; if ((str = in.readLine()) != null) { System.out.println(str); } in.close(); 用两个字节编码,但您读为ASCII,则可能会返回两个字符,这与原始文件不匹配。