SuperCSV – CsvBeanReader,CellProcessor,CsvBeanWriter

时间:2020-02-23 14:35:36  来源:igfitidea点击:

SuperCSV的动力将是针对Java的最重要,最快和最方便程序员的免费CSV软件包。
不幸的是,我们在Java中没有内置的CSV解析器。

超级CSV

Java中有许多开源CSV解析器。
但是SuperCSV分析器是我的最爱。
超级CSV解析器的功能是具有许多功能的" CellProcessor"。
您可以将列值指定为NotNull,可选,唯一。
SuperCSV单元处理器还支持日期时间转换,乔达时间,枚举等。

今天,我们将研究SuperCSV示例,以读取CSV文件并将其转换为Java对象列表。
我们还将快速浏览Super CSV示例程序,以编写CSV数据。

在研究示例之前,我们必须创建示例CSV数据和相应的java bean。

1,hyman Kumar,20,San Franceco
2,David Dan,40,USA
3,Lisa Ray,28,Germany

我们对应的Java bean类是" Employee.java",如下所示。

package com.theitroad.csv.model;

public class Employee {

	private String id;
	private String name;
	private String age;
	private String country;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	@Override
	public String toString() {
		return "{" + id + "::" + name + "::" + age + "::" + country + "}";
	}
}

SuperCSV Maven

在您的maven项目pom.xml文件中添加以下依赖项以获取Super CSV jar。

<dependency>
	<groupId>net.sf.supercsv</groupId>
	<artifactId>super-csv</artifactId>
	<version>2.4.0</version>
</dependency>

SuperCSV CsvBeanReader

这是一个简单的Super CSV示例程序,使用CsvBeanReader来解析java对象的CSV数据列表。

package com.theitroad.csv.supercsv.parser;

import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.UniqueHashCode;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;

import com.theitroad.csv.model.Employee;

public class SuperCSVParserExample {

	public static void main(String[] args) throws IOException {

		List<Employee> emps = new ArrayList<Employee>();
		ICsvBeanReader beanReader = new CsvBeanReader(new FileReader("emps.csv"), CsvPreference.STANDARD_PREFERENCE);
		
		//the name mapping provide the basis for bean setters
		final String[] nameMapping = new String[] { "id", "name", "age", "country" };
		
		//to read and skip header row
		//final String[] header = beanReader.getHeader(true);
		
		final CellProcessor[] processors = getProcessors();
		Employee emp;
		while ((emp = beanReader.read(Employee.class, nameMapping, processors)) != null) {
			emps.add(emp);
		}
		System.out.println(emps);
		beanReader.close();

	}

	private static CellProcessor[] getProcessors() {
		final CellProcessor[] processors = new CellProcessor[] { 
				new UniqueHashCode(), //ID
				new NotNull(), //Name
				new Optional(), //Age
				new NotNull() //Country
		};
		return processors;
	}

}

该程序简单易懂,最重要的部分是创建超级CSV单元处理器。

如果您的CSV文件包含标题行,请使用beanReader.getHeader(true)读取并跳过标题以进行处理。

SuperCSV CsvBeanWriter

一个简单的超级CSV示例,使用CsvBeanWriter写入CSV数据。
我假设年龄和国家/地区字段是可选的。

package com.theitroad.csv.supercsv.parser;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.UniqueHashCode;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;

import com.theitroad.csv.model.Employee;

public class SuperCSVWriterExample {

	public static void main(String[] args) throws IOException {
		List<Employee> emps = generateDemoData();

		StringWriter writer = new StringWriter();
		ICsvBeanWriter beanWriter = new CsvBeanWriter(writer, CsvPreference.STANDARD_PREFERENCE);
		final String[] header = new String[] { "id", "name", "age", "country" };
		final CellProcessor[] processors = getProcessors();

		//write the header
		beanWriter.writeHeader(header);

		//write the beans data
		for (Employee emp : emps) {
			beanWriter.write(emp, header, processors);
		}

		beanWriter.close();

		System.out.println("CSV Data\n" + writer.toString());
	}

	private static CellProcessor[] getProcessors() {
		final CellProcessor[] processors = new CellProcessor[] { new UniqueHashCode(), //ID
				new NotNull(), //Name
				new Optional(), //Age
				new Optional() //Country
		};
		return processors;
	}

	private static List<Employee> generateDemoData() {
		List<Employee> emps = new ArrayList<>();
		Employee emp = new Employee();
		emp.setId("1");
		emp.setName("hyman Kumar");
		emp.setAge("30"); //country is optional and not set
		Employee emp1 = new Employee();
		emp1.setId("2");
		emp1.setName("David");
		emp1.setCountry("USA"); //age is optional
		Employee emp2 = new Employee();
		emp2.setId("3");
		emp2.setName("Lisa");
		emp2.setAge("20");
		emp2.setCountry("San Franceco");

		emps.add(emp);
		emps.add(emp1);
		emps.add(emp2);

		return emps;
	}

}

上面的程序产生下面的CSV输出。

CSV Data
id,name,age,country
1,hyman Kumar,30,
2,David,,USA
3,Lisa,20,San Franceco

如果您不希望标题行,请在上面的程序中注释代码beanWriter.writeHeader(header)

如果更改上述程序以使两个Employee对象的ID保持相同,则将获得以下异常。

Exception in thread "main" org.supercsv.exception.SuperCsvConstraintViolationException: duplicate value '2' encountered with hashcode 50
processor=org.supercsv.cellprocessor.constraint.UniqueHashCode
context={lineNo=4, rowNo=4, columnNo=1, rowSource=[2, Lisa, 20, San Franceco]}
	at org.supercsv.cellprocessor.constraint.UniqueHashCode.execute(UniqueHashCode.java:78)
	at org.supercsv.util.Util.executeCellProcessors(Util.java:93)
	at org.supercsv.io.CsvBeanWriter.write(CsvBeanWriter.java:136)
	at com.theitroad.csv.supercsv.parser.SuperCSVWriterExample.main(SuperCSVWriterExample.java:33)

原因是我们已将id列定义为具有UniqueHashCode约束。
这是一个非常独特且重要的功能,在Java中的所有其他CSV解析器中都没有。