这是我的代码:
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader = new BufferedReader(new FileReader(file));
char[] buf = new char[5000];
int numRead=0;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString();
当我在Windows中运行时,一切都很好。
但是当我在字符串的开头用UNIX运行时,我看到了:

可能是什么问题?
答案 0 :(得分:3)
给定char序列的hexdump
可能是ef bb bf
。我可能会说,因为我不得不猜测你的显示编码。
如果这是正确的,您尝试将ISO-8859-X读作UTF-8编码文件with BOM prefix。这与使用vi / vim打开文件时看不到这些字符的事实是一致的。大多数(如果不是全部)支持UTF-8的文本编辑器都知道如何处理BOM。
从Java开始,您必须手动跳过它(不知道它为什么在Windows上运行)。 另一种选择是将文本文件保存为UTF-8 而不用 BOM。
这已经讨论过了。例如见:
由于这不是很清楚,我做了以下实验:我创建了两个文件, utf-8 编码并包含字符串“L'élèvevaàl 'école。“这两个测试文件之间的唯一区别是一个有BOM前缀。
然后,根据OP提供的代码和Thomas Mueller的建议,我编写了一个非常简单的Java应用程序来使用各种编码来读取这些文件。这是代码:
public class EncodingTest {
public static String read(String file, String encoding) throws IOException {
StringBuffer fileData = new StringBuffer(1000);
/* Only difference with OP code */
/* I use *explicit* encoding while reading the file */
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(file), encoding)
);
char[] buf = new char[5000];
int numRead=0;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
}
reader.close();
return fileData.toString();
}
public static void main(String[] args) throws IOException {
System.out.print(read("UTF-8-BOM-FILE", "UTF-8"));
System.out.print(read("UTF-8-FILE", "UTF-8"));
System.out.print(read("UTF-8-BOM-FILE", "ISO-8859-15"));
System.out.print(read("UTF-8-FILE", "ISO-8859-15"));
}
}
当我在Linux系统上运行此控制台编码为UTF8时,我得到以下结果:
$ java -cp bin EncodingTest
L'élève va à l'école.
L'élève va à l'école.
L'élÚve va à l'école.
L'élÚve va à l'école.
注意第三行是如何以与OP 给出的完全相同的顺序开始的。那是在读取 utf8编码文件时将BOM作为iso-8859-15 。
令人惊讶的是,前两行似乎是相同的,就像Java神奇地删除了BOM一样。我想这就是在Windows上附加OP的内容。
但仔细观察后发现:
$ java -cp bin EncodingTest | hexdump -C
00000000 ef bb bf 4c 27 c3 a9 6c c3 a8 76 65 20 76 61 20 |...L'..l..ve va |
00000010 c3 a0 20 6c 27 c3 a9 63 6f 6c 65 2e 0a 4c 27 c3 |.. l'..cole..L'.|
00000020 a9 6c c3 a8 76 65 20 76 61 20 c3 a0 20 6c 27 c3 |.l..ve va .. l'.|
00000030 a9 63 6f 6c 65 2e 0a c3 af c2 bb c2 bf 4c 27 c3 |.cole........L'.|
00000040 83 c2 a9 6c c3 83 c5 a1 76 65 20 76 61 20 c3 83 |...l....ve va ..|
00000050 c2 a0 20 6c 27 c3 83 c2 a9 63 6f 6c 65 2e 0a 4c |.. l'....cole..L|
00000060 27 c3 83 c2 a9 6c c3 83 c5 a1 76 65 20 76 61 20 |'....l....ve va |
00000070 c3 83 c2 a0 20 6c 27 c3 83 c2 a9 63 6f 6c 65 2e |.... l'....cole.|
00000080 0a |.|
00000081
请注意前三个字节:BOM已发送到输出 - 但我的控制台以某种方式丢弃了它们。但是,从Java程序的角度来看,那些存在的字节 - 我应该可以手动处理它们。
那么,这一切的道德是什么? OP确实存在两个问题:BOM前缀为UTF8编码文件。该文件读作iso-8859-X。
Yuris,为了解决这个问题,您必须在Java程序中明确使用正确的编码,和要么丢弃前3个字节或更改您的数据文件以删除BOM。
答案 1 :(得分:0)
byte[] content = Files.readAllBytes(file.toPath());
String s = new String(bytes, StandardCharsets.UTF_8);
s = s.replaceFirst("^\uFEFF", ""); // Remove starting BOM
return s;
BOM是一个字节顺序标记,可选地用作第一个char,零宽度空间,用于将文件标记为UTF-8(或UTF-16LE,UTF-16BE)。
它的主要用途似乎是在Windows上用于NotePad而不是将文本与ANSI编码混淆。
FileReader是一个无法设置编码的实用程序类。
可能是您的文件已经遭遇了错误的编码转换。也许UTF-8文本被粘贴到ANSI单字节编码文本中,或者其他任何内容。