Java中的字符编码
我用记事本打开文件,在上面写:“ą”保存并关闭 我试着用两种方式阅读这个文件 第一:Java中的字符编码,java,utf-8,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"));
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,采用哪种编码
我试图理解为什么会有差异您得到的是
拉丁字母的十进制
值
您需要使用UTF-8
编码标准保存文件
当你用类似的标准阅读它们时,一定要确保
0x0105 261带OGONEKą的拉丁文小写字母A
0x00C4 196带分音符的拉丁文大写字母A�
请参阅:-尝试使用UTF-8编码的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格式读取,那么您可能会返回两个字符,这两个字符与原始文件不匹配。因为您以不同的编码读取这两个字母,所以可以通过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 ą
UTF-8将范围U+0080
-U+07FF
中的值编码为两个字节,格式为110xxxxx
10xxxxxx
(更多信息请参见)。因此,只有xxxxx xxxxxx
11个字节可用于值
ą
是其中的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
分为(两个字节):
现在,InputStream
将数据读取为原始字节。因此,当您调用inputStream.read()时代码>第一次获取11000100
时,它是以十进制表示的196
。调用inputStream.read()
第二次将返回10000101
,它是十进制的133
Reader
s是在Java1.1中引入的,因此我们可以避免代码中出现这种混乱。相反,我们可以指定编码读取器应该使用什么(或让它使用默认值)来获得正确编码的值,如本例中的00000001 00000101
(不带掩码),它等于十六进制形式的0105
,十进制形式的261
总之
- 如果要以文本形式读取数据,请使用
Reader
s(使用正确指定的编码)
- 如果要将数据作为原始字节读取,请使用
Stream
s
您将一个字符的文件保存在记事本中的编码是什么?记事本++显示“utf-8无bom”,但我在utf-8表“ą”中没有看到带有代码的字母:196 OP已经意识到了这一点。所以,他不是这个意思。字符ą
编码为两个字节(C4 85
),其中C4
是十进制的196
。所以他们实际上只读取了第一个字节。@TiiJ7谢谢你的侦探工作。我不知道该如何解决这个问题,但编码问题是我首先想到的:-)
110xxxxx 10xxxxxx
00100 000101
11000100 10000101