你能推荐一个Java库来读取(并可能写)CSV文件吗?

时间:2008-10-14 10:08:20

标签: java parsing csv

你能推荐一个Java库来读取,解析,验证和映射逗号分隔值(CSV)文件中的行到Java值对象(JavaBeans)吗?

8 个答案:

答案 0 :(得分:36)

我们已经习惯了 http://opencsv.sourceforge.net/ 取得了不错的成就

我还遇到了另一个有良好链接的问题: Java lib or app to convert CSV to XML file?

答案 1 :(得分:23)

Super CSV是阅读/解析,验证CSV文件并将其映射到POJO的绝佳选择!

我们(Super CSV团队)刚刚发布了一个新版本(您可以从SourceForge或Maven download发布它。)

读取CSV文件

以下示例使用CsvDozerBeanReader(我们刚刚发布的一个新的阅读器,它使用Dozer进行bean映射,具有深度映射和基于索引的映射支持) - 它基于我们{的示例{3}}。如果您不需要Dozer功能(或者您只是想要一个简单的独立依赖项),那么您可以使用CsvBeanReader代替(请参阅此website)。

示例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都会被读入code example类,每个类都有一个SurveyResponse列表。为了使映射起作用,您的类应该是有效的Javabeans(即具有默认的无参数构造函数并且为每个字段定义了getter / setter)。

在超级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有一个有用的Answer库,可用于将字符串从CSV文件转换为其他数据类型(例如Date,Integer),或进行约束验证(例如强制/可选,正则表达式匹配,范围检查)。

使用单元格处理器完全是可选的 - 没有它们,每列CSV都是一个字符串,所以每个字段也必须是一个字符串。

以下是该示例的单元处理器配置。与字段映射一样,数组中的每个元素都代表一个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文件等中读取),并且可以通过{{配置分隔符和引号字符3}}(其中有许多预定义的配置可以满足大多数用途)。

以下代码非常明显。

  1. 创建阅读器(包含您的Reader和偏好设置)

  2. (可选)阅读标题

  3. 配置bean映射

  4. 继续致电read(),直至收到null(文件结尾)

  5. 关闭阅读器

  6. <强>代码:

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

    更多信息

    您可以在cell processors上找到更多信息!

答案 2 :(得分:7)

我可以推荐SuperCSV。简单易用,并做了我需要的一切。

答案 3 :(得分:4)

嘿,我有一个开源项目:JFileHelpers。我认为主要的优点是它使用Java Annotations,看看:

如果你有这个bean:

@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");

此外,它还支持主细节,日期和格式转换等等。让我知道你的想法!

祝你好运!

答案 4 :(得分:3)

我发现Flatpack非常适合处理奇怪的CSV文件(转义,引号,错误记录等)

答案 5 :(得分:2)

之前询问的CSV文件到XML问题似乎回答了我的所有问题。

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)似乎也做了我需要的一切 - 特别是绑定到Java对象 - 除了支持FLR和XML

答案 6 :(得分:0)

我使用OpenCSV从Java解析和编写CSV文件取得了很好的成功。如果您想使用Java读取或编写Excel兼容的电子表格,那么Apache的POI库就可以了。

答案 7 :(得分:0)

请参阅CVSBeans