首页 > 编程语言 >java 解析csv

java 解析csv

时间:2023-06-28 14:37:08浏览次数:43  
标签:解析 java header2 header3 header1 SimpleBeanInfo CsvToBean new csv


opencsv

java读取csv的类库主要有两种,opencsv和javacsv,研究发现,javacsv最后一次更新是2014-12-10,很久不维护了。opencsv是apache的项目,并且至今仍在维护,所以决定使用opencsv。


csv

csv文件,全名 comma separated values,默认以逗号分隔,是纯文本文件。虽然用excel打开后格式排版了,但是那是excel对他进行了处理。用notepad或者sublime text打开能看到最原始的文本。
为了后续举例,这里编辑了一个test.csv

header1,header2,header3
1,a,10
2,b,20
3,c,30
4,d,40
5,e,50
6,f,60

读取方式

  • 最原始的方式,逐行读取,然后操作
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));
	  
	  /*
	   * 逐行读取
	   */
	  String[] strArr = null;
	  while((strArr = reader.readNext())!=null){
		  System.out.println(strArr[0]+"---"+strArr[1]+"----"+strArr[2]);
	  }
	  
	  reader.close();

绑定csv文件转换成bean

逐行读取操作是最原始的操作方式,opencsv提供了基于“策略”的映射,将csv绑定到bean。

策略简介

观察一下策略的继承层次

java 解析csv_开发语言

接口
  • MappingStrategy
  • 映射的顶层接口
  • HeaderColumnNameMappingStrategy
  • 列名映射策略,读取csv文件第一行作为header,比如header1,header2,header3,然后调用bean的setHeader1方法,setHeader2方法,setHeader3方法分别设置值,所以这种策略要求,列名与bean中的属性名完全一致,如果不一致,则值为空,不会出错。使用注解时,注解名字必须与csv中列名一致。
  • ColumnPositionMappingStrategy
  • 列位置映射策略,他没有header的概念,所以会输出取所有行。在columnMapping数组中指定bean的属性,第一个值对应csv的第一列,第二个值对应csv的第二类…
  • HeaderColumnNameTranslateMappingStrategy
  • 列头名字翻译映射策略,与HeaderColumnNameMappintStrategy相比,bean的属性名可以与csv列头不一样。通过指定map来映射。

具体映射用法

Java POJO类
public class SimpleBeanInfo {

	private String header1;
	

	private String header2;
	
	private String header3;

	public String getHeader1() {
		return header1;
	}

	@Override
	public String toString() {
		return "SimpleBeanInfo [header1=" + header1 + ", header2=" + header2
				+ ", header3=" + header3 + "]";
	}

	public void setHeader1(String header1) {
		this.header1 = header1;
	}

	public String getHeader2() {
		return header2;
	}

	public void setHeader2(String header2) {
		this.header2 = header2;
	}

	public String getHeader3() {
		return header3;
	}

	public void setHeader3(String header3) {
		this.header3 = header3;
	}

基于列索引的映射
  • 通俗点来说就是列位置映射,csv文件中的列位置对应到bean中的列
  • 非注解方式
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));
	  /*
	   *基于列位置,映射成类 
	   */
	   //csv文件中的第一列对应类的header,第二列对应类的header2,第三列对应类的header3
	  String[] columnMapping={"header1","header2","header3"};
	  ColumnPositionMappingStrategy<SimpleBeanInfo> mapper = new ColumnPositionMappingStrategy<SimpleBeanInfo>();
	  mapper.setColumnMapping(columnMapping);
	  mapper.setType(SimpleBeanInfo.class);
	  /* */ 
	  CsvToBean<SimpleBeanInfo>  csvToBean = new CsvToBean<SimpleBeanInfo>();

	  List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader);
	  
	  for(SimpleBeanInfo e : list){
		  System.out.println(e);
	  }
		   
	}
  • 注解方式
public class SimpleBeanInfo {

	@CsvBindByPosition(position=0)
	private String header1;
	

	@CsvBindByPosition(position=1)
	private String header2;
	
	@CsvBindByPosition(position=2)
	private String header3;
}
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));
 ColumnPositionMappingStrategy<SimpleBeanInfo> mapper = new ColumnPositionMappingStrategy<SimpleBeanInfo>();
	  mapper.setType(SimpleBeanInfo.class);
	  CsvToBean<SimpleBeanInfo>  csvToBean = new CsvToBean<SimpleBeanInfo>();
		 
	  List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader);
	  
	  for(SimpleBeanInfo e : list){
		  System.out.println(e);
	  }

基于列名的映射
  • 非注解方式
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));
	 
	  /* */ 
	  
	  HeaderColumnNameMappingStrategy<SimpleBeanInfo> mapper = new
			  HeaderColumnNameMappingStrategy<SimpleBeanInfo>();
	  mapper.setType(SimpleBeanInfo.class);
	  CsvToBean<SimpleBeanInfo>  csvToBean = new CsvToBean<SimpleBeanInfo>();
	 
	  List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader);
	  
	  for(SimpleBeanInfo e : list){
		  System.out.println(e);
	  }
  • 注解方式
public class SimpleBeanInfo {

	@CsvBindByName(column="header1")
	private String header1;
	
	
	@CsvBindByName(column="header2")
	private String header2;
	
	@CsvBindByName(column="header3")
	private String header3;
}
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));

	  HeaderColumnNameMappingStrategy<SimpleBeanInfo> mapper = new
			  HeaderColumnNameMappingStrategy<SimpleBeanInfo>();
	  mapper.setType(SimpleBeanInfo.class);
	  CsvToBean<SimpleBeanInfo>  csvToBean = new CsvToBean<SimpleBeanInfo>();
	 
	  List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader);
	  
	  for(SimpleBeanInfo e : list){
		  System.out.println(e);
	  }

基于列名转换映射
CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream("test.csv"),"gbk"));
	  /*
	   * 基于列名转换,映射成类
	  */
	  HeaderColumnNameTranslateMappingStrategy<SimpleBeanInfo> mapper = 
			  new HeaderColumnNameTranslateMappingStrategy<SimpleBeanInfo>();
	  mapper.setType(SimpleBeanInfo.class);
	  
	  Map<String,String> columnMapping = new HashMap<String,String>();
	  columnMapping.put("header1", "header1");//csv中的header1对应bean的header1
	  columnMapping.put("header2", "header2");
	  columnMapping.put("header3", "header3");
	  mapper.setColumnMapping(columnMapping);
	  
	  CsvToBean<SimpleBeanInfo>  csvToBean = new CsvToBean<SimpleBeanInfo>();
		 
	  List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader);
	  
	  for(SimpleBeanInfo e : list){
		  System.out.println(e);
	  }

过滤器

opencsv提供了过滤器,可以过滤某些行,比如page header、page footer等

  • 所有的过滤器必须实现CsvToBeanFilter 接口
public class MyCsvToBeanFilter implements CsvToBeanFilter {
		
		public boolean allowLine(String[] line) {
		    //过滤第一列值等于1的行
			if("1".equals(line[0])){
				return false;
			}
	 		return true;
	 	}

}
MyCsvToBeanFilter filter = new MyCsvToBeanFilter();
 List<SimpleBeanInfo> list = csvToBean.parse(mapper, reader,filter);

转化器

类中的属性不一定都是字符串,比如数字、日期等,但是我们从csv中获取到的都是字符串,这种情况就应该使用转化器。
这里定义一个SimpleBeanConverter,继承AbstractBeanField

public class SimpleBeanFieldConverter extends AbstractBeanField<SimpleBeanInfo> {

	@Override
	protected Object convert(String value) throws CsvDataTypeMismatchException,
			CsvRequiredFieldEmptyException, CsvConstraintViolationException {
		Field f = getField();
		if("date".equals(f.getName())){
			try {
				return new SimpleDateFormat("yyyy-MM-dd").parse(value);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
}

test.csv添加一列header4

header1,header2,header3,header4
1,a,10,2016-05-01
2,b,20,2016-05-02
3,c,30,2016-05-03
4,d,40,2016-05-04
5,e,50,2016-05-05
6,f,60,2016-05-06

SimpleBeanInfo添加属性

@CsvCustomBindByPosition(position=3,converter=SimpleBeanFieldConverter.class)
private Date date;

输出结果
由于ColumnPositionMappingStrategy会连header行也解析,所以第一行会打印异常信息。我们看到header4列已经转换为日期。如果不只一个列需要转换怎么办?在相应的属性上添加注解(@CsvCustomBindByPosition或@CsvCustomBindByName),然后在convert(Object value)中扩展即可

java.text.ParseException: Unparseable date: "header4"
	at java.text.DateFormat.parse(DateFormat.java:357)
	at test_maven.SimpleBeanFieldConverter.convert(SimpleBeanFieldConverter.java:24)
	at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:70)
	at com.opencsv.bean.CsvToBean.processField(CsvToBean.java:245)
	at com.opencsv.bean.CsvToBean.processLine(CsvToBean.java:220)
	at com.opencsv.bean.CsvToBean.processLine(CsvToBean.java:189)
	at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:166)
	at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:133)
	at test_maven.TestCSV.main(TestCSV.java:46)
SimpleBeanInfo [header1=header1, header2=header2, header3=header3, date=null]
SimpleBeanInfo [header1=2, header2=b, header3=20, date=Mon May 02 00:00:00 CST 2016]
SimpleBeanInfo [header1=3, header2=c, header3=30, date=Tue May 03 00:00:00 CST 2016]
SimpleBeanInfo [header1=4, header2=d, header3=40, date=Wed May 04 00:00:00 CST 2016]
SimpleBeanInfo [header1=5, header2=e, header3=50, date=Thu May 05 00:00:00 CST 2016]
SimpleBeanInfo [header1=6, header2=f, header3=60, date=Fri May 06 00:00:00 CST 2016]

公众号

欢迎关注个人公众号

java 解析csv_List_02


标签:解析,java,header2,header3,header1,SimpleBeanInfo,CsvToBean,new,csv
From: https://blog.51cto.com/u_15561616/6571864

相关文章

  • java 序列化 serialVersionUID transient
    问题再现User类实现了序列化,但是没有声明版本号,这个对象放在memcache中,User新添加了1个字段后,把之前的对象从缓存中取出来时,出现了InvalidClassException,为什么会出现这个错误?序列化序列化就是将对象转为流,用于传输或保存。序列化的是“对象状态”,所以就不包括静态变量;反序列化是从......
  • java8 LocalDateTime/LocalDate/LocalTime、java.util.Date/java.sql.Date区别及日期
    先介绍一下,LocalDateTime/LocalDate/LocalTime、java.util.Date/java.sql.Date区别LocalDateTime/LocalDate/LocalTimejava.time.LocalDateTime,是一个日期+时间,不带时区,它是个不可更改对象,精确到纳秒。它的日期可以认为是生日,它的时间可以认为是挂钟的时间,比较LocalDateTime时用eq......
  • 在linux上启动arthas报“Can not find java process”
    发生背景完整报错信息:[***@localhost~]$java-jararthas-boot.jar[INFO]JAVA_HOME:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b03-1.el7.x86_64/jre[INFO]arthas-bootversion:3.6.9[INFO]Cannotfindjavaprocess.Trytorun`jps`commandliststheinstrume......
  • 3、Apache Kudu集成impala(shell和java操作)的详细操作
    ApacheKudu系列文章1、ApacheKudu介绍及架构、工作原理、两种部署方式、使用限制详解2、ApacheKudu-javaapi操作kudu详细示例以及kudu的三种实现示例3、ApacheKudu集成impala(shell和java操作)的详细操作(文章目录)本文简单的介绍了通过impala操作kudu,包括通过shell和......
  • 浅谈 Kotlin 与 Java 互操作 (上)
    前言浅谈Kotlin与Java互操作(上)Kotlinis100%interoperablewithJavaandAndroidKotlin官网的一句标语,其旨意是表达kotlin的Interoperable-互操作特性互操作就表示Kotlin中可以调用Java的开放接口来访问成员属性和成员方法,同时在Java代码中也百分百兼容Kotlin......
  • Java-IDEA的基础设置及插件安装,让IDEA更好用!
     Java-IDEA的基础设置及插件安装,让IDEA更好用!IDEA简单配置教程:https://mp.weixin.qq.com/s/Z5QLYyvjiiS0xg9wpSTvewIDEA高效使用插件:https://mp.weixin.qq.com/s/ShnHX9uxd4esiYHOA8TZvQIDEA快捷键操作指南:https://blog.csdn.net/qq_38963960/article/details/89552704 ......
  • java 异步方法总结(减少主线程阻塞)
    主要点第一点:@Async只能使用到被代理的对象方法上,即代理类的入口方法处,且方法必须是public的。第二点:事务处理机制使用@Async异步注解不能和@Transaction事务注解在同一个方法上同时使用,不然事务注解将无效。要使用事务,需要把事务注解提取到方法里面的子方法上。  代码实......
  • 2、Apache Kudu-java api操作kudu详细示例以及kudu的三种实现示例
    ApacheKudu系列文章1、ApacheKudu介绍及架构、工作原理、两种部署方式、使用限制详解2、ApacheKudu-javaapi操作kudu详细示例以及kudu的三种实现示例3、ApacheKudu集成impala(shell和java操作)的详细操作(文章目录)本文介绍了javaapi操作kudu详细示例以及kudu的三种......
  • JAVA常用类---静态内部类
    publicclassOuter{privateStringname="李四";privateStringsex="男";//静态类和外部类权限一样/*外部调用Outer.Interinter=newOuter.Inter();Outer.Inter仅表示包含关系,如果是成员类应为Outer.Interinter=newOuter().Inter();还需要导......
  • 【Flutter专题】Android Flutter入门笔记、技术解析与项目实战
    Flutter是一个跨平台、高性能的移动UI框架,其采用Dart语言开发,并使用自己的渲染引擎来绘制UI,保证了自身的高性能,保证了在Android和iOS上UI的一致性。目前Flutter已经支持iOS、Android、Web、Windows、macOS、Linux、Fuchsia(Google新的自研操作系统)等众多平台。与其他跨平......