需求是读取一个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头的文件遇到的问题的更多相关文章

  1. linux下查找包含BOM头的文件和清除BOM头命令

    查找包含BOM头的文件,命令如下:   grep -r -I -l $'^\xEF\xBB\xBF' ./   这条命令会查找当前目录及子目录下所有包含BOM头的文件,并把文件名在屏幕上输出.   但 ...

  2. Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50

    Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50 分类: 系统运维 查找包含BOM头的文件,命令如下: 点击(此处)折叠或打开 grep -r -I -l ...

  3. python学习——读取染色体长度(六:读取含有染色体长度的文件)

    含有染色体长的文件chr_len.txt chr1 10chr2 20chr3 30chr4 40chr5 50 python脚本 #传递命令行参数 import sys # 导入模块 # 从命令行获 ...

  4. 檢查php文件中是否含有bom的php文件

    原文链接: http://www.cnblogs.com/Athrun/archive/2010/05/27/1745464.html 另一篇文章:<关于bom.php>,http://h ...

  5. 检测文件是否有BOM 头,并删除BOM头(php)

    将下面文件放在网站根目录访问即可,它会遍历当前目录下所有子目录,检测文件是否含有BOM头,并删除BOM头 <?php //remove the utf-8 boms //by magicbug ...

  6. Java处理文件BOM头的方式推荐

    背景: java普通的文件读取方式对于bom是无法正常识别的. 使用普通的InputStreamReader,如果采用的编码正确,那么可以获得正确的字符,但bom仍然附带在结果中,很容易导致数据处理出 ...

  7. C#写UTF8文件时指定是否含BOM头

    BOM的基本概念 在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF.而FFFE在UCS中是不存在的字符,所以不应该出现在实 ...

  8. PHP批量去除文件BOM头

    auto 是否自动替换 默认否 dir 检查目录 默认./ display 是否显示所有文件 默认只显示有bom头的文件 <?php empty($_GET['auto']) && ...

  9. C#·对于BOM头之完全解决方案

    阅文时长 | 0.46分钟 字数统计 | 798.4字符 主要内容 | 1.引言&背景 2.使用C#写入带有/不带有BOM头的文件? 3.对于读取文件时,避免BOM头造成的异常. 4.声明与参 ...

随机推荐

  1. PHPSTUDY下升级mysql后无法启动

    说来也是搞笑,之前很早就想看Laravel了~其中,之前项目忙,还有就是自己也出了点事故!但是呢,我个人哭过,抱怨过,但是我还是很懂我自己的.也许没心没肺也是一种好事,但也是坏事~ 闲话说多了,来说正 ...

  2. Cypher查询语言--Neo4j 综合(四)

    目录 返回节点 返回关系 返回属性 带特殊字符的标识符 列的别名 可选属性 特别的结果   查询中的返回部分,返回途中定义的感兴趣的部分.可以为节点.关系或其上的属性. 图 返回节点 返回一个节点,在 ...

  3. Intellij IDEA 15 如何同时打开多个项目

    标题:Intellij IDEA 15 如何同时打开多个项目 作者原创技术文章,转载请注明出处 我们在编程时常常需要打开多个项目,例如操作复制黏贴或者参考其他项目等等,但是编译器Intellij ID ...

  4. xBIM 使用Linq 来优化查询

    目录 xBIM 应用与学习 (一) xBIM 应用与学习 (二) xBIM 基本的模型操作 xBIM 日志操作 XBIM 3D 墙壁案例 xBIM 格式之间转换 xBIM 使用Linq 来优化查询 x ...

  5. Oracle常见授权与回收权限——grant和revoke

    1.GRANT 赋于权限常用的系统权限集合有以下三个:CONNECT(基本的连接), RESOURCE(程序开发), DBA(数据库管理) 常用的数据对象权限有以下五个:ALL ON 数据对象名, S ...

  6. C 洛谷 P3599 Koishi Loves Construction [构造 打表观察]

    题目描述 Koishi决定走出幻想乡成为数学大师! Flandre听说她数学学的很好,就给Koishi出了这样一道构造题: Task1:试判断能否构造并构造一个长度为的的排列,满足其个前缀和在模的意义 ...

  7. Oracle的order by的中文排序问题

    Oracle 中查询结果按照某个中文字段或者英文字母(包括 符号)排序,并不会得到我们预期的结果,因为对于中文与英文字母及符号,Oracle实际是按照其对应的ASCII码值排序的! 可以看到按照中文村 ...

  8. document.activeElement 过滤选择文件弹窗导致的页面失焦

    在线考试页面,常常需要检测用户是否作弊. 一般是监听页面是否失焦的方式,而失焦的方式有很多种,比如QQ弹窗,切换页面,切换程序,input文件上传选择文件等 选择文件是正常情况,这种情况下需要过滤 本 ...

  9. webrtc底层一对一连接过程探索(三)

    一.连接过程继续解读-----fun33-fun35解读 完整代码如下: //fun33-37 console.error('fun35-37==>2332==>2332'); var q ...

  10. 【模板小程序】求第n个fibonacci数

    //fibonacci,find the nth num. 1 1 2 3 5 8... #include <iostream> using namespace std; int fib( ...