从文件中读取特殊字符 - Java

3

我正在读取一个具有以下属性的文本文件:

编码:ANSI
文件类型:PC

现在,该文件包含许多特殊字符,如度符号(º)等。我正在使用以下代码读取此文件:

File file = new File("C:\\X\\Y\\SpecialCharacter.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));

如果文件编码为ANSI,则上述代码无法正确读取特殊字符,例如文件中的行:
“将热量降低并煨,直到产品达到165ºF的内部温度”,reader.readLine()输出:
“将热量降低并煨,直到产品达到165�F的内部温度”。

当我将文件编码更改为UTF-8时,该行就会像文件中一样读取,而不会弄乱特殊字符。

我的问题是,在什么时候数据会出现问题?在将数据存储在文件中还是从文件中读取时?在记事本中打开文件可以正确显示所有特殊字符。这是如何发生的?

Hexdump 输出:

          -0 -1 -2 -3  -4 -5 -6 -7  -8 -9 -A -B  -C -D -E -F

00000000- 4C 6F 77 65  72 20 68 65  61 74 20 61  6E 64 20 73 [Lower heat and s]
00000001- 69 6D 6D 65  72 20 75 6E  74 69 6C 20  70 72 6F 64 [immer until prod]
00000002- 75 63 74 20  72 65 61 63  68 65 73 20  69 6E 74 65 [uct reaches inte]
00000003- 72 6E 61 6C  20 74 65 6D  70 65 72 61  74 75 72 65 [rnal temperature]
00000004- 20 6F 66 20  31 36 35 BA  46                       [ of 165.F       ]

请在此贴出该文件中的那一行的hexdump,这样我们就可以确定 'º' 如何被编码了。 - Mike Samuel
@MikeSamuel:已添加所提到文本的输出。 - name_masked
2个回答

9
"ANSI"不是一种特定的编码方式 - 它是一整个编码系列。读取文件时需要使用正确的编码方式。例如,您可能正在使用 Windows-1252 编码,这意味着您可能需要尝试将 "Cp1252" 作为编码名称传入。
实际上,您正在传入 "UTF-8",它并不是通常所说的 ANSI 编码之一。您需要找出文件使用的确切编码方式,然后在 InputStreamReader 参数中指定该编码方式。
假设编码能够表示您感兴趣的所有字符,那么只有在读取文件时才会出现问题。基本上,您正在尝试按照一种编码方式读取文件,而实际上文件采用的是另一种编码方式。记事本要么执行某种启发式编码检测,要么恰好对于这种特定情况使用了正确的默认设置。

“在这种特定情况下使用正确的默认值是正确的。”是正确的。记事本经常无法正确读取我的文件。另一方面,Wordpad在某种程度上确实可以检测编码。 - Sheriff
@Jon Skeet:所以我想确认一下,当文件中涉及特殊字符时,使用的编码完全取决于创建该文件的程序/JVM默认设置。当我查看文件属性时,编码方式是“通用”的?例如,如果我现在在我的系统上创建一个文件,并且System.getProperty("file.encoding")返回UTF-8,那么同一文件的文件属性将显示编码为UTF-8 - name_masked
@darkie15:你说的“文件属性”是指什么? - Jon Skeet
@JonSkeet:在Textpad编辑器中右键单击文件选项卡时看到的属性,或者在Notepad中执行“保存/另存为..”操作时可以看到/设置的属性(在这种情况下,仅限编码)。 - name_masked
@darkie15:这取决于程序想要做什么。例如,Textpad和Notepad并不一定会达成一致。它不是文本文件中的数据的一部分 - 因此必须基于启发式猜测。 - Jon Skeet

1

new InputStreamReader(new FileInputStream(file), "UTF-8") 用于读取 UFT-8 编码的文件:如果您要读取不同编码(例如 Win 1252)的文件,则应相应更改第二个参数。

文本文件在编码方面永远不会出现问题:它以某种编码存储,您应该在读取时使用相同的编码,以便系统可以解释原始字节流并将每个[组]字节与适当的字符[或 Unicode 代码点,如果我们正在执行 Unicode]相关联,以便您能够看到“正确”的字形。

希望这能稍微澄清一下。

祝好


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接