参考:http://jybzjf.iteye.com/blog/2262392
java读取编码有bom文件之前是有bug,后来修复了。
但是JDK8中新增了Files的Stream操作好像依然不支持bom文件读取。
读取文件行数据使用的是Files.lines,使用方法如下:
//读取所有内容
List<String> lines = Files.readAllLines(Paths.get("g://test.txt"), Charsets.UTF_8);
//读取部分内容
long index = 0l; //从0行开始读
int limit = 10; //读取10行内容
Files.lines(Paths.get("g://test.txt"), Charsets.UTF_8)
.skip(index)
.limit(limit)
.forEach(line -> {
//对每行内容做处理
});
可以看到JDK8后使用Files的stream操作可以只用一行代码,甚至不用写文件输入输出流、缓冲就能方便读写文件。
但是也因此又出现了读写文件编码带bom的bug。
开篇参考链接里面的资料是java适配了编码带bom文件的读写,其中处理编码带bom文件的主要代码如下:
//注意:jdk8里,UnicodeInputStream类又有了一些细微的变化
File f = new File("D:"+File.separator+"Order.txt");
FileInputStream in = new FileInputStream(f);
String dc = Charset.defaultCharset().name();
UnicodeInputStream uin = new UnicodeInputStream(in,dc);
BufferedReader br = new BufferedReader(new InputStreamReader(uin));
String line = br.readLine();
UnicodeInputStream 就是处理带bom文件的处理类。
但是Files.lines都已经封装好了,参数只能传文件路径,并且也没有提供参数是文件流的接口。怎么处理呢?
接下来我们看下Files.lines方法源码。
public static Stream<String> lines(Path path, Charset cs) throws IOException {
BufferedReader br = Files.newBufferedReader(path, cs);
try {
return br.lines().onClose(asUncheckedRunnable(br));
} catch (Error|RuntimeException e) {
try {
br.close();
} catch (IOException ex) {
try {
e.addSuppressed(ex);
} catch (Throwable ignore) {}
}
throw e;
}
}
源码里实际上也是对BufferedReader进行处理,既然如此我们可以在自己的代码这么用:
UnicodeInputStream uis = new UnicodeInputStream(Files.newInputStream(Paths.get(path)), true);//true表示不读取bom字符
BufferedReader br = new BufferedReader(new InputStreamReader(uis, charset));
br.lines().onClose(asUncheckedRunnable(br))
.skip(this.index)
.limit(this.limit)
.forEach(line -> {
System.out.pinrtln(line);
});
uis.close();
asUncheckedRunnable方法直接从源码里面拷出来
private static Runnable asUncheckedRunnable(Closeable c) {
return () -> {
try {
c.close();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
这样就可以用Files的stream操作读取编码带bom的文件了。