java opencsv解析csv文件
记一次使用opencsv解析csv文件时碰到的坑
最近在开发过程中需要解析csv文件,公司用的解析工具是opencsv,在根据opencsv的官方文档去解析时发现csv文件中含有繁体字,使用其自带的CsvToBean来转换会出现异常com.opencsv.exceptions.CsvRequiredFieldEmptyException: Number of data fields does not match number of headers.于是我这里想到的方法是使用CsvReader来读取文件,然后通过反射来注入到bean中,这里做个记录希望对大家有帮助
一、引入依赖包
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.4</version>
</dependency>
二、具体代码
1.自定义注解,基础一点的就是只需要定义数据列标题名title、格式转换convert,我这里是由于业务需要所以稍微复杂些
import java.lang.annotation.*; /**
* <p>
* 解析csv文件注解
* </p>
*
* @Author zlc0w01
* @Date 2020/4/20 10:15
* @Version 1.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CsvReadColmn {
/**
* 该列数据的标题名
*/
String title(); /**
* 是否需要加密
*/
boolean encrypt() default false; /**
* 读csv文件字段绑定
* 绑定格式转换类,字符串转Object
* @return
*/
Class<? extends AbstractConvertCsvBase> convert() default AbstractConvertCsvBase.Converter.class; /**
* 转换依赖字段,如有某个字段转换需要依赖其他字段,
* 可设置为依赖字段的title
* @return
*/
String convertRelyColumn() default ""; }
2.接下来就是定义用于转换的基类了,这里面可以自己定义,我这里定义的意思是转换所有字段,去掉前面的单引号“'”,其他需要定义的转换规则可以继承这个类,然后重写convert方法就行了
public abstract class AbstractConvertCsvBase {
private static final String SPLIT = "'";
/**
* 转换
* @param params 参数中必须有key为"value"
* @return
*/
public Object startConvert(Map<String,String> params){
String value = params.get("value");
if (StringUtils.isNotBlank(value) && SPLIT.equals(value.substring(0,1))){
value = value.substring(1);
}
if (StringUtils.isBlank(value)){
return null;
}
params.put("value",value);
return convert(params);
}
/**
* 转换方法
* @param params
* @return
*/
public abstract Object convert(Map<String,String> params);
public static class Converter extends AbstractConvertCsvBase{
public static Converter newInstance() {
return new Converter();
}
@Override
public Object convert(Map<String,String> params) {
return params.get("value");
}
}
}
3.定义需要转换的bean
public class GbInsurancePolicy implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@CsvReadColmn(title = "内部号码")
private String id;
@CsvReadColmn(title = "出生日期",convert = CsvConvertStringToSimpleDate.class)
private Date birthday;
}
//上面说到定义转换规则,这里拿出生日期举例
public class CsvConvertStringToSimpleDate extends AbstractConvertCsvBase {
@SneakyThrows
@Override
public Object convert(Map<String, String> params) {
String value = params.get("value");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
return sf.parse(value);
}
}
4.定义反射来解析csv文件
public List<T> readSpecialCsv(String filePath) throws Exception{
List<T> list = new ArrayList<>();
FileInputStream fr = new FileInputStream(filePath);
UnicodeInputStream unicodeInputStream = new UnicodeInputStream(fr, true);
String enc = unicodeInputStream.getEncodingFromStream();
InputStreamReader is = new InputStreamReader(unicodeInputStream, enc);
CSVReader reader = new CSVReader(is);
String [] nextLine;
String[] header = reader.readNext();
while ((nextLine = reader.readNext()) != null) {
if (nextLine.length < header.length){
continue;
}
T t = getTClass().newInstance();
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Field fieldName = t.getClass().getDeclaredField(field.getName());
CsvReadColmn csvReadColmn = fieldName.getAnnotation(CsvReadColmn.class);
if (null != csvReadColmn){
int columnPosition = Arrays.asList(header).indexOf(csvReadColmn.title());
String value = nextLine[columnPosition];
AbstractConvertCsvBase convert = csvReadColmn.convert().newInstance();
Map<String,String> params = new HashMap<>();
params.put("value",value);
//是否有需要依赖某个字段来转换的
if (StringUtils.isNotBlank(csvReadColmn.convertRelyColumn())){
int relyColumnPosition = Arrays.asList(header).indexOf(csvReadColmn.convertRelyColumn());
String relyColumn = nextLine[relyColumnPosition];
params.put("relyColumn",relyColumn);
}
Object obj = convert.startConvert(params);
String methodName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Method m = t.getClass().getDeclaredMethod(methodName, fieldName.getType());
m.invoke(t, obj);
}
}
list.add(t);
}
reader.close();
return list;
}
以上就是整个流程,希望对大家有帮助
java opencsv解析csv文件的更多相关文章
- php解析.csv文件
public function actionImport() { //post请求过来的 $fileName = $_FILES['file']['name']; $fileTmpName = $_F ...
- JAVA简便解析json文件
JAVA简便解析json文件 首先放上我要解析的json文件: { "resultcode":"200", "reason":"S ...
- [cocos2dx utils] cocos2dx读取,解析csv文件
在我们的游戏中,经常需要将策划的数值配置成csv文件,所以解析csv文件就是一个很common的logic, 例如如下csv文件: 下面是一个基于cocos2dx 2.2.4的实现类: #ifndef ...
- Qt解析CSV文件
最近需要解析Excel文件,于是顺带写了解析CSV的代码 定义数据类型LX::Sheet #ifndef LX_H #define LX_H #include <QString> #inc ...
- .NET 上传并解析CSV文件存库
1.前端: 放置浏览按钮 <div class="row inner_table text-center"> <input id="fileId&quo ...
- Java jdom解析xml文件带冒号的属性
Java jdom解析xml文件带冒号的属性 转载请标明出处: https://dujinyang.blog.csdn.net/article/details/99644824 本文出自:[奥特曼超人 ...
- 如何用Java解析CSV文件
首先看一下csv文件的规则: csv(Comma Separate Values)文件即逗号分隔符文件,它是一种文本文件,可以直接以文本打开,以逗号分隔.windows默认用excel打开.它的格式包 ...
- 解析 csv文件 java ***最爱那水货
/** * csv文件解析 <br> * wx 微信明细数据 第1行是标题 ,最后2行 是总结 提取数据需要过滤<br> * zfb 支付宝明细数据 前4行 和最后4行是总结 ...
- selenium3 文件系列之------ opencsv读取csv文件
最近在学习selenium有关文件的读取测试,今天先总结一下如何读取csv文件.CSV的定义是与逗号分隔的值(Comma-Separated Values),在Java中需要用到第三方lib去处理读取 ...
随机推荐
- elasticSearch插件metricbeat收集nginx的度量指标
ngx_http_stub_status_module模块是Nginx中用来统计Nginx服务所接收和处理的请求数量,只要在编译安装Nginx的时候加上参数--with-http_stub_statu ...
- 观察者模式(Observer Pattern)(二):HeadFirst中的气象站的实现
1 观察者模式的原理,首先由一个主题,当主题发送变化的时候,通知该主题的订阅者 按照上面的分析我们来进行设计 1.抽象主题Subject public interface Subject { publ ...
- 网络虚拟化之linux虚拟网络基础
1 linux虚拟网络基础 1.1 Device 在linux里面devic(设备)与传统网络概念里的物理设备(如交换机.路由器)不同,Linux所说的设备,其背后指的是一个类似于数据结构.内核模块或 ...
- .net core docker容器编排部署(linux)
环境准备 需要一个linux操作系统:我这里用的是ubuntu 18.04,安装步骤就不说了,网上很多教程,当然也可以私信我. 既然需要用到docker,那么就安装个docker,apt instal ...
- Vue 封装axios(四种请求)及相关介绍(十三)
Vue 封装axios(四种请求)及相关介绍 首先axios是基于promise的http库 promise是什么? 1.主要用于异步计算 2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的 ...
- 【CSGRound1】天下第一 题解
[CSGRound1]天下第一 https://www.luogu.com.cn/problem/P5635 分析题目: 题目中说明,有T组数据,但是mod只有一个.很显然,这道题可以用记忆化搜索嘛! ...
- Django---进阶6
目录 聚合查询 分组查询 F与Q查询 django中如何开启事务 orm中常用字段及参数 数据库查询优化 图书管理系统 作业 聚合查询 # 聚合查询 aggregate ""&qu ...
- 大致掌握django的功能
目录 静态文件配置 request对象方法初识 pycharm链接数据库(mysql) django链接数据库(mysql) django orm 字段的增删查改 数据的增删查改 数据的查,改,删 d ...
- 开发者必备——API设计问题
本文主要探讨RPC和RESTFul两种API风格的特点以及在开发中应该如何进行技术选型,同时截取了网上社区,文章一部分关于API设计的想法和观点供读者参考,取舍. 1,背景简述 API学名:应用程序接 ...
- day58 前端收尾
目录 一.jQuery结束 1 阻止后续事件执行 2 阻止事件冒泡 3 事件委托 4 页面加载 5 动画效果 6 补充知识点 二.前端框架Bootstrap 1 布局容器 2 栅格系统 3 栅格参数 ...