前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解析csv文件兼容bom头

解析csv文件兼容bom头

作者头像
叔牙
修改2021-12-21 19:50:24
1.9K0
修改2021-12-21 19:50:24
举报

背景

接上一篇《安装配置Sftp并通过java访问》,由于我们上传的文件是通过程序生成标准的文件csv格式文件,而乙方是通过人肉的方式把外呼结果汇总之后创建txt文件然后修改后缀的方式变成csv文件,这样会导致我们程序解析的时候遇到一些问题,比如bom文件头问题(他们是windows系统,只有windows系统把txt改成csv会出现bom头问题),导致我们程序解析出错,当然我们作为一个有品德有追求的程序员,肯定不会学他们通过有功的方式去解析,那么接下来就通过程序兼容的方式,解析带bom头的csv文件。

解析兼容

引入依赖

代码语言:javascript
复制
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-csv</artifactId>
  <version>1.5</version>
</dependency>

1.常规csv文件解析

代码语言:javascript
复制
List<T> resultList = new ArrayList<>();
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
ByteArrayInputStream byteArrayInputStream = null;
CSVParser parser = null;
try {
    byteArrayInputStream = new ByteArrayInputStream(bytes);
    inputStreamReader = new InputStreamReader(byteArrayInputStream);
    //reader = new UnicodeReader(byteArrayInputStream,"utf-8");
    //bufferedReader = new BufferedReader(reader);
    bufferedReader = new BufferedReader(inputStreamReader);
    parser = CSVFormat.DEFAULT
            .withHeader("a","b")
            .withFirstRecordAsHeader()
            .parse(bufferedReader);
    //int rowIndex = 0;
    for (CSVRecord record : parser.getRecords()) {
        //transfer record to row
        T row = ...
        log.info("read data from ftp;row={}",row);
        resultList.add(row);
    }
} catch (UnsupportedEncodingException e) {
    log.error("occur error;filePath={}",filePath,e);
} catch (IOException e) {
    log.error("occur error;filePath={}",filePath,e);
} catch (Exception e) {
    log.error("occur error;filePath={}",filePath,e);
} finally {
    IOUtils.closeQuietly(byteArrayInputStream);
    IOUtils.closeQuietly(inputStreamReader);
    //IOUtils.closeQuietly(reader);
    IOUtils.closeQuietly(bufferedReader);
    IOUtils.closeQuietly(parser);
}

这种情况下解析常规的csv文件没有任何问题,但是带bom头的文件解析不了。原因是csv理论上也是纯文本文件,不排除认为的生成txt文件通过改后缀名的方式变成了csv文件,或者在windows平台手动生成的csv,都是带bom头的,用命令打开文件的时候会发现文件头部有乱码现象。

2.使用bom流解析兼容

代码语言:javascript
复制
List<T> resultList = new ArrayList<>();
BufferedReader bufferedReader = null;
InputStreamReader inputStreamReader = null;
ByteArrayInputStream byteArrayInputStream = null;
BOMInputStream bomInputStream = null;
CSVParser parser = null;
try {
    byteArrayInputStream = new ByteArrayInputStream(bytes);
    //使用BOMInputStream兼容bom头csv文件
    bomInputStream = new BOMInputStream(byteArrayInputStream,false, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE,ByteOrderMark.UTF_8);
    String charset = "UTF-8";
    if(bomInputStream.hasBOM()) {
        charset = bomInputStream.getBOMCharsetName();
    }
    inputStreamReader = new InputStreamReader(bomInputStream, Charset.forName(charset));
    //reader = new UnicodeReader(byteArrayInputStream,"utf-8");
    //bufferedReader = new BufferedReader(reader);
    bufferedReader = new BufferedReader(inputStreamReader);
    parser = CSVFormat.DEFAULT
            .withHeader("a","b")
            .withFirstRecordAsHeader()
            .parse(bufferedReader);
    //int rowIndex = 0;
    for (CSVRecord record : parser.getRecords()) {
    T row = ...
        log.info("read data from ftp;row={}",row);
        resultList.add(row);
    }
} catch (UnsupportedEncodingException e) {
    log.error("occur error;filePath={}",filePath,e);
} catch (IOException e) {
    log.error("occur error;filePath={}",filePath,e);
} catch (Exception e) {
    log.error("occur error;filePath={}",filePath,e);
} finally {
    IOUtils.closeQuietly(byteArrayInputStream);
    IOUtils.closeQuietly(bomInputStream);
    IOUtils.closeQuietly(inputStreamReader);
    IOUtils.closeQuietly(bufferedReader);
    IOUtils.closeQuietly(parser);
}

原理是bom流能检测到bom头,且在流中exclude掉bom。

3.使用UnicodeReader解析兼容

类似以上代码:

代码语言:javascript
复制
UnicodeReader ur = new UnicodeReader(fis, "utf-8"); 
bufferedReader = new BufferedReader(ur);

UnicodeReader 通过PushbackInputStream+InputStreamReader实现BOM的自动检测和过滤读取;当没有检测到BOM时,pushback流将回退,并采用构造函数传入的编码进行读取。否则使用BOM对应的编码进行读取。

总结

对于上一节的2和3,相对来说,3方式更加轻量和强大;另外也更加透明,可以随便修改源码来实现自己的需求。

UnicodeReader参考:http://akini.mbnet.fi/java/unicodereader/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 解析兼容
    • 1.常规csv文件解析
      • 2.使用bom流解析兼容
        • 3.使用UnicodeReader解析兼容
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档