今天在做一个文件上传的项目中碰到了一个十分奇怪的问题,在解析上传上来的csv文件时,总是在解析第一行的第一个标题字段时出错,就是第一个那个字段总是和对应的model字段对应不上,这个坑是真的很深,找了半天,发现原来utf8编码格式的文件可能会有BOM头这玩意儿!
我们先来看看什么是BOM头:
在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示该文件属于utf-8编码。
现在已经有很多软件识别bom头,但是还有些不能识别bom头,比如PHP就不能识别bom头,这也是用记事本编辑utf-8编码后执行就会出错的原因了。
最坑的是这个bom头在记事本中是完全看不见的,当记事本指定的编码格式是默认的ANSI编码时,文件的内容解析是没有任何问题的。但是,这样会出现中文乱码的情况,一般在项目中都会统一使用utf8编码,在我在记事本中指定了utf8编码格式上传后,才出现了字段解析不正确的情况。
那么怎么处理掉这个BOM头呢,在java中apache提供了一个工具类BOMStream,在获取文件流时,将获取到的文件流转化成为BOM流:
1 InputStreamReader isr = new InputStreamReader (new BOMInputStream (fileInputStream), "utf8");
这样以来,读取的文件中即使有BOM头,也会被自动过滤掉。但是这种方法只能过滤掉UTF-8/UTF-16LE/UTF-16BE三种编码格式的文件,当文件是其他格式时,就会失效。
要想支持更多的编码格式的文件,只能使用另外一个工具了:UnicodeStream和UnicodeReader,其使用示例如下:
1 FileInputStream fis = new FileInputStream(file); 2 UnicodeReader ur = new UnicodeReader(fis, "utf-8"); 3 BufferedReader br = new BufferedReader(ur);
这种方式更加的通用与强大。推荐使用这种方法。