您能推荐一个Java库来读取、解析、验证逗号分隔值(CSV)文件中的行并将其映射到Java值对象(JavaBeans)吗?
我们使用http://opencsv.sourceforge.net/成功的
我还遇到了另一个链接良好的问题:Java库或应用程序将CSV转换为XML文件?
Super CSV是读取/解析、验证CSV文件并将其映射到POJO的绝佳选择!
我们(超级CSV团队)刚刚发布了一个新版本(您可以从SourceForge或Maven下载)。
读取CSV文件
下面的示例使用CsvDozerBeanReader
(我们刚刚发布的一个新阅读器,它使用Dozer进行bean映射,并支持深度映射和基于索引的映射)——它基于我们网站上的示例。如果您不需要Dozer功能(或者您只想要一个简单的独立依赖项),那么您可以使用CsvBeanReader
(请参阅此代码示例)。
CSV文件示例
下面是一个示例CSV文件,它表示对调查的响应。它有一个标题和3行数据,全部有8列。
age,consentGiven,questionNo1,answer1,questionNo2,answer2,questionNo3,answer3
18,Y,1,Twelve,2,Albert Einstein,3,Big Bang Theory
,Y,1,Thirteen,2,Nikola Tesla,3,Stargate
42,N,1,,2,Carl Sagan,3,Star Wars
定义从CSV到POJO的映射
CSV的每一行都将被读取到SurveyResponse类中,每个类都有一个答案列表。为了使映射工作,您的类应该是有效的Javabean(即,具有默认的无arg构造函数,并为每个字段定义getter/setter)。
在Super CSV中,您可以用一个简单的String数组定义映射——数组的每个元素都对应于CSV文件中的一列。
使用CsvDozerBeanMapper
,您可以使用:
简单字段映射(例如
firstName
)深度映射(例如
address.country.code
)索引映射(例如
middleNames[1]
-数组或集合的基于零的索引)深度+索引映射(例如
person.middleNames[1]
)
以下是本例的字段映射-它使用了以下内容的组合:
private static final String[] FIELD_MAPPING = new String[] {
"age", // simple field mapping (like for CsvBeanReader)
"consentGiven", // as above
"answers[0].questionNo", // indexed (first element) + deep mapping
"answers[0].answer",
"answers[1].questionNo", // indexed (second element) + deep mapping
"answers[1].answer",
"answers[2].questionNo",
"answers[2].answer" };
转换和验证
Super CSV有一个有用的单元格处理器库,可用于将CSV文件中的字符串转换为其他数据类型(例如Date、Integer),或进行约束验证(例如强制/可选、正则表达式匹配、范围检查)。
使用单元格处理器是完全可选的-如果没有它们,CSV的每一列都将是一个字符串,因此每个字段也必须是一个String。
以下是示例的单元处理器配置。与字段映射一样,数组中的每个元素都表示一个CSV列。它演示了单元格处理器如何将CSV数据转换为字段的数据类型,以及如何将它们链接在一起。
final CellProcessor[] processors = new CellProcessor[] {
new Optional(new ParseInt()), // age
new ParseBool(), // consent
new ParseInt(), // questionNo 1
new Optional(), // answer 1
new ParseInt(), // questionNo 2
new Optional(), // answer 2
new ParseInt(), // questionNo 3
new Optional() // answer 3
};
阅读
使用Super CSV读取非常灵活:您可以提供自己的Reader
(这样您就可以从文件、类路径、zip文件等中读取),分隔符和引号可以通过首选项进行配置(其中有许多预定义的配置适合大多数用途)。
下面的代码非常不言自明。
创建阅读器(带有您的
Reader
和偏好)(可选)读取标题
配置bean映射
继续调用
read()
,直到得到null
(文件末尾)关闭读卡器
代码:
ICsvDozerBeanReader beanReader = null;
try {
beanReader = new CsvDozerBeanReader(new FileReader(CSV_FILENAME),
CsvPreference.STANDARD_PREFERENCE);
beanReader.getHeader(true); // ignore the header
beanReader.configureBeanMapping(SurveyResponse.class, FIELD_MAPPING);
SurveyResponse surveyResponse;
while( (surveyResponse =
beanReader.read(SurveyResponse.class, processors)) != null ) {
System.out.println(
String.format("lineNo=%s, rowNo=%s, surveyResponse=%s",
beanReader.getLineNumber(), beanReader.getRowNumber(),
surveyResponse));
}
} finally {
if( beanReader != null ) {
beanReader.close();
}
}
输出:
lineNo=2, rowNo=2, surveyResponse=SurveyResponse [age=18, consentGiven=true, answers=[Answer [questionNo=1, answer=Twelve], Answer [questionNo=2, answer=Albert Einstein], Answer [questionNo=3, answer=Big Bang Theory]]]
lineNo=3, rowNo=3, surveyResponse=SurveyResponse [age=null, consentGiven=true, answers=[Answer [questionNo=1, answer=Thirteen], Answer [questionNo=2, answer=Nikola Tesla], Answer [questionNo=3, answer=Stargate]]]
lineNo=4, rowNo=4, surveyResponse=SurveyResponse [age=42, consentGiven=false, answers=[Answer [questionNo=1, answer=null], Answer [questionNo=2, answer=Carl Sagan], Answer [questionNo=3, answer=Star Wars]]]
更多信息
你可以在网站上找到更多的信息!
我可以推荐SuperCSV。简单易用,做了我需要的一切。
嘿,我有一个开源项目:JFileHelpers。我认为主要的优点是它使用了Java注释,看看:
如果你有这个豆子:
@FixedLengthRecord()
public class Customer {
@FieldFixedLength(4)
public Integer custId;
@FieldAlign(alignMode=AlignMode.Right)
@FieldFixedLength(20)
public String name;
@FieldFixedLength(3)
public Integer rating;
@FieldTrim(trimMode=TrimMode.Right)
@FieldFixedLength(10)
@FieldConverter(converter = ConverterKind.Date,
format = "dd-MM-yyyy")
public Date addedDate;
@FieldFixedLength(3)
@FieldOptional
public String stockSimbol;
}
并且想要解析这个文件:
....|....1....|....2....|....3....|....4
1 Antonio Pereira 10012-12-1978ABC
2 Felipe Coury 201-01-2007
3 Anderson Polga 4212-11-2007DEF
你所要做的就是:
FileHelperEngine<Customer> engine =
new FileHelperEngine<Customer>(Customer.class);
List<Customer> customers =
new ArrayList<Customer>();
customers = engine.readResource(
"/samples/customers-fixed.txt");
此外,它还支持主细节、日期和格式转换等。让我知道你的想法!
致以最良好的问候!
我发现Flatpack非常擅长处理古怪的CSV文件(转义、引号、坏记录等)
OpenCSV(http://opencsv.sourceforge.net/)还使用列位置映射策略绑定JavaBeans
ColumnPositionMappingStrategy strat = new ColumnPositionMappingStrategy();
strat.setType(YourOrderBean.class);
String[] columns = new String[] {"name", "orderNumber", "id"}; // the fields to bind do in your JavaBean
strat.setColumnMapping(columns);
CsvToBean csv = new CsvToBean();
List list = csv.parse(strat, yourReader);
JSEFA(http://jsefa.sourceforge.net)除了支持FLR和XML
之外,似乎还可以完成我需要的一切,特别是绑定到Java对象我使用OpenCSV从Java解析和编写CSV文件都取得了很好的成功。如果你想用Java阅读或编写Excel兼容的电子表格,Apache的POI库就是你的选择。
请参阅CVSBeans