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去处理读取 ...
随机推荐
- IDEA+Maven+Tomcat构建Web项目的三种方法
[本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 本文将介绍三种方 ...
- elasticsearch中query和filter的区别
参考博客来自: https://mp.weixin.qq.com/s/tiiveCW3W-oDIgxvlwsmXA?utm_medium=hao.caibaojian.com&utm_sour ...
- 入门大数据---Spark车辆监控项目
一.项目简介 这是一个车辆监控项目.主要实现了三个功能: 1.计算每一个区域车流量最多的前3条道路. 2.计算道路转换率 3.实时统计道路拥堵情况(当前时间,卡口编号,车辆总数,速度总数,平均速度) ...
- Build completed with 1 error and 0 warnings in 20 ms
今天运行Idea,好端端的项目居然报了这个莫名其妙的错误Build completed with 1 error and 0 warnings in 20 ms. 首先排查下代码是否有问题,然后我就建 ...
- JDK8--06:Stream流
一.描述 Stream流提供了筛选与切片.映射.排序.匹配与查找.归约.收集等功能 筛选与切片: filter:接收lambda,从流中排除某些元素 limit(n):截断流,使其元素不超过n ski ...
- JNI调用Cython生成库‘undefined symbol: PyInit_’问题
最近项目需要提升所有 Python 算法的执行时间,并给 Java 框架调用,根据 Python一键转Jar包,Java调用Python新姿势!的思路可以用 Cython 将 Python 代码转换为 ...
- mdcChipSet中mdcChip事件selectedChange
项目中遇到一个问题,由于每个mdcChip上都有一个change事件,所以想在change事件中操作执行最新被选中的item时,就会遇到一些麻烦. 如何解决呢? 全局设置一个变量,例如:mark 然后 ...
- HDU5961 传递
传递 因为文化课复习实在捉急qwq,题解就一切从简了qwq 简单说一说 上来一看这道题没看出来突破点在哪... 去HDU上看原题,发现原题是带样例的图解的,然鹅还是没找到思路(太菜了吧) 没办法看了一 ...
- UVA1464 Traffic Real Time Query System
传送门:https://www.luogu.com.cn/problem/UVA1464 看到这道题,求必经的点数,还是无向图.那么妥妥的圆方树.圆方树上的任意两圆点间的路径必定是圆点方点相交错的,对 ...
- .NET Core使用AngleSharp网络数据采集
环境: vs2019 .net core 3.1 angleSharp winform 安装:angleSharp 有这么一本Python的书: <<Python 网络数据采集>&g ...