java解析csv(代码片段)

wangjun5159 wangjun5159     2023-03-28     200

关键词:

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。

策略简介

观察一下策略的继承层次

接口

  • 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]

公众号

欢迎关注个人公众号

sql解析csv字符串。(代码片段)

查看详情

python在不使用csv的情况下解析csv文件(代码片段)

查看详情

java解析csv(代码片段)

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

csharp将csv文件解析为表(代码片段)

查看详情

python解析蜡烛棒文件并输出到csv(代码片段)

查看详情

java示例代码_验证使用CSV备份的输入数据,无需专门构建的CSV解析器

java示例代码_验证使用CSV备份的输入数据,无需专门构建的CSV解析器 查看详情

python解析csv中的多维字典(代码片段)

CSV文件结构如下,其中字段A为唯一代码如下,Python271withopen(file_obj+‘TEST.CSV‘,‘r‘)asf:2#转为字典3Reader=csv.DictReader(f)4#转为列表,列表中多维字典5csvlist1=list(Reader)6#将A当做为索引7csvlist2=[row[‘A‘]forrowincsvlist1]8#根据A的值找到下... 查看详情

powershellpowershell脚本用于解析csv中的xml并展开它(代码片段)

查看详情

下载一个zip,解压缩并解析它-全部在内存中-java(代码片段)

...访问.zip中的CSV文件,并使用ApacheCommonsCSV在CSVRecords列表中解析它们。我不想将任何文件写入磁盘,因为这是一种性能浪费。这是我到目前为止(我现在省略了所有错误处理,它只是一个POC):URLurl=newURL(myURLString);InputStreaminp 查看详情

python解析用于knowbe4电子邮件上传的csv文件(代码片段)

查看详情

字符串csv解析表格逗号分隔值(代码片段)

CSV文件简介逗号分隔值(Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被... 查看详情

csv文件的读写(代码片段)

...章句子信息等,这些信息‘,‘符是常用字符,容易造成解析出错或者解析方法复杂。可以选用‘^‘/‘ ‘等不常用的字符作为分隔符。应用途而异,具体问题具体分析。  2.写入csv文件Filecsv=newFile(“path”);BufferedWrit... 查看详情

fetch_csv使用(代码片段)

...ts1.简述2.使用googledrive发布csv文件3.algorithm中读取csv文件4.解析csv文件4.1.日期范围需要设置正确4.2.获取某个字段4.3.通过pre函数获取dataframe1 简述目标是通过csv文件提供每日推荐股票,然后让algrithm解析csv文件的内容后进行backt... 查看详情

html问ben:使用javascriptexec()正则表达式命令解析csv字符串(代码片段)

查看详情

如何上传csv文件并解析它?(代码片段)

我需要上传csv文件并解析它。我可以在http正文请求中看到文件,但是当我在csvreader中传递它时,我可以看到像标题一样的base64字符串:在客户端我使用angularjs:'uploadBulkUsersFile':method:'POST',url:CONFIG.apiServiceBaseUri+"api/users/bulkUsers",he... 查看详情

yolov5解析|绘制results.csv文件数据对比图(代码片段)

功能描述我们在写论文过程中,通常是需要附带上改进后YOLOv5算法与改进前YOLOv5算法的mAP_0.5值对比图,可以使用下面的代码来生成这个对比图。代码实现importcsvimportmatplotlib.pyplotaspltimportpandasaspdimportnumpyasnpplt.rcParams['fo... 查看详情

text从s3获取json对象,将其解析为csv,然后将其放回s3(代码片段)

查看详情

java中csv文件读写分析(代码片段)

...sv使用场景四、Java中的csv类库1.javacsv2.opencsv写入器读取器解析器注解映射策略过滤器构建器写入方式①简单的写入②基于位置映射的写入③基于CsvBindByPosition注解映射的写入④基于列名映射的写入⑤基于CsvBindByName注解映射的写入... 查看详情