我用记事本打开文件,在其中写上:“±”保存并关闭。
我尝试以两种方式读取此文件
第一:
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,采用哪种编码?
我试图理解为什么存在差异
答案 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带有首字母缩略词的拉丁文大写字母
答案 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,则可能会返回两个字符,这与原始文件不匹配。