读取含有BOM头的文件遇到的问题
需求是读取一个csv文件,然后解析成对应的数据结构。csv必须包含指定的某些列,通过列名header来进行校验。
解析配置文件的方法。
public List<QuestionData> buildConfigData(final MultipartFile file) {
CsvReader csvReader = null;
List<QuestionData> questionDataList;
try (DataInputStream inputStream = new DataInputStream(file.getInputStream())) {
csvReader = new CsvReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
if (!csvReader.readHeaders()) {
return Lists.newLinkedList();
}
final String[] headers = csvReader.getHeaders();
getAndCheckHeader(headers);
questionDataList = getQuestionData(csvReader, headers);
} catch (final IOException e) {
log.error("解析配置文件错误", e);
throw new FatalException("解析配置文件错误");
} finally {
if (csvReader != null) {
csvReader.close();
}
}
return questionDataList;
}
其中,检查header的方法:
private static final Set<String> NEEDED_COLUMNS = ImmutableSet
.of(QuestionDataType.ORDER.name(), QuestionDataType.DESC.name(), QuestionDataType.OPTION_A.name(),
QuestionDataType.OPTION_B.name(), QuestionDataType.OPTION_C.name(), QuestionDataType.ANSWER.name()); private void getAndCheckHeader(final String[] headers) {
//某些必要的列不存在
HashSet<String> sets = Sets.newHashSet(headers);
if (!sets.containsAll(NEEDED_COLUMNS)) {
throw new FatalException("缺少必要的列信息");
}
}
实际出现的问题是,上传文件的时候总是出现缺少必要的列信息这个异常。debug发现,containsAll这个方法一直返回false,但是看NEEDED_COLUMNS里面的字符串,在header里面都存在,例如ORDER字符串:

从这里看,headers里面有ORDER字符串,但是NEEDED_COLUMNS.contains(headers[0])返回的结果就是false。
debug时使用evaluate,将headers[0]的value copy一下,粘贴到输入框里,就发现了问题:

可以看的出来,headers[0]的实际值是"\uFEFFORDER",而非"ORDER",前面多了一个"\uFEFF"。
经查,"\uFEFF"是BOM头,windows下保存文件时经常会插入在字符串最前面,debug时直接看值是看不出来有这个BOM头的。
解决方案,使用apache的BOMInputStream,可以过滤掉BOM头:
public List<QuestionData> buildConfigData(final MultipartFile file) {
CsvReader csvReader = null;
List<QuestionData> questionDataList;
//过滤BOM头
try (BOMInputStream inputStream = new BOMInputStream(file.getInputStream())) {
csvReader = new CsvReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
if (!csvReader.readHeaders()) {
return Lists.newLinkedList();
}
final String[] headers = csvReader.getHeaders();
getAndCheckHeader(headers);
questionDataList = getQuestionData(csvReader, headers);
} catch (final IOException e) {
log.error("解析配置文件错误", e);
throw new FatalException("解析配置文件错误");
} finally {
if (csvReader != null) {
csvReader.close();
}
}
return questionDataList;
}
使用BOMInputStream,将原有的InputSteam包一层即可。
参考文章:Java处理文件BOM头的方式推荐
读取含有BOM头的文件遇到的问题的更多相关文章
- linux下查找包含BOM头的文件和清除BOM头命令
查找包含BOM头的文件,命令如下: grep -r -I -l $'^\xEF\xBB\xBF' ./ 这条命令会查找当前目录及子目录下所有包含BOM头的文件,并把文件名在屏幕上输出. 但 ...
- Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50
Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50 分类: 系统运维 查找包含BOM头的文件,命令如下: 点击(此处)折叠或打开 grep -r -I -l ...
- python学习——读取染色体长度(六:读取含有染色体长度的文件)
含有染色体长的文件chr_len.txt chr1 10chr2 20chr3 30chr4 40chr5 50 python脚本 #传递命令行参数 import sys # 导入模块 # 从命令行获 ...
- 檢查php文件中是否含有bom的php文件
原文链接: http://www.cnblogs.com/Athrun/archive/2010/05/27/1745464.html 另一篇文章:<关于bom.php>,http://h ...
- 检测文件是否有BOM 头,并删除BOM头(php)
将下面文件放在网站根目录访问即可,它会遍历当前目录下所有子目录,检测文件是否含有BOM头,并删除BOM头 <?php //remove the utf-8 boms //by magicbug ...
- Java处理文件BOM头的方式推荐
背景: java普通的文件读取方式对于bom是无法正常识别的. 使用普通的InputStreamReader,如果采用的编码正确,那么可以获得正确的字符,但bom仍然附带在结果中,很容易导致数据处理出 ...
- C#写UTF8文件时指定是否含BOM头
BOM的基本概念 在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF.而FFFE在UCS中是不存在的字符,所以不应该出现在实 ...
- PHP批量去除文件BOM头
auto 是否自动替换 默认否 dir 检查目录 默认./ display 是否显示所有文件 默认只显示有bom头的文件 <?php empty($_GET['auto']) && ...
- C#·对于BOM头之完全解决方案
阅文时长 | 0.46分钟 字数统计 | 798.4字符 主要内容 | 1.引言&背景 2.使用C#写入带有/不带有BOM头的文件? 3.对于读取文件时,避免BOM头造成的异常. 4.声明与参 ...
随机推荐
- PHPSTUDY下升级mysql后无法启动
说来也是搞笑,之前很早就想看Laravel了~其中,之前项目忙,还有就是自己也出了点事故!但是呢,我个人哭过,抱怨过,但是我还是很懂我自己的.也许没心没肺也是一种好事,但也是坏事~ 闲话说多了,来说正 ...
- Cypher查询语言--Neo4j 综合(四)
目录 返回节点 返回关系 返回属性 带特殊字符的标识符 列的别名 可选属性 特别的结果 查询中的返回部分,返回途中定义的感兴趣的部分.可以为节点.关系或其上的属性. 图 返回节点 返回一个节点,在 ...
- Intellij IDEA 15 如何同时打开多个项目
标题:Intellij IDEA 15 如何同时打开多个项目 作者原创技术文章,转载请注明出处 我们在编程时常常需要打开多个项目,例如操作复制黏贴或者参考其他项目等等,但是编译器Intellij ID ...
- xBIM 使用Linq 来优化查询
目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...
- Oracle常见授权与回收权限——grant和revoke
1.GRANT 赋于权限常用的系统权限集合有以下三个:CONNECT(基本的连接), RESOURCE(程序开发), DBA(数据库管理) 常用的数据对象权限有以下五个:ALL ON 数据对象名, S ...
- C 洛谷 P3599 Koishi Loves Construction [构造 打表观察]
题目描述 Koishi决定走出幻想乡成为数学大师! Flandre听说她数学学的很好,就给Koishi出了这样一道构造题: Task1:试判断能否构造并构造一个长度为的的排列,满足其个前缀和在模的意义 ...
- Oracle的order by的中文排序问题
Oracle 中查询结果按照某个中文字段或者英文字母(包括 符号)排序,并不会得到我们预期的结果,因为对于中文与英文字母及符号,Oracle实际是按照其对应的ASCII码值排序的! 可以看到按照中文村 ...
- document.activeElement 过滤选择文件弹窗导致的页面失焦
在线考试页面,常常需要检测用户是否作弊. 一般是监听页面是否失焦的方式,而失焦的方式有很多种,比如QQ弹窗,切换页面,切换程序,input文件上传选择文件等 选择文件是正常情况,这种情况下需要过滤 本 ...
- webrtc底层一对一连接过程探索(三)
一.连接过程继续解读-----fun33-fun35解读 完整代码如下: //fun33-37 console.error('fun35-37==>2332==>2332'); var q ...
- 【模板小程序】求第n个fibonacci数
//fibonacci,find the nth num. 1 1 2 3 5 8... #include <iostream> using namespace std; int fib( ...