你能推荐一个 Java 库来读取(并且可能写入)CSV 文件吗? [关闭]

Posted

技术标签:

【中文标题】你能推荐一个 Java 库来读取(并且可能写入)CSV 文件吗? [关闭]【英文标题】:Can you recommend a Java library for reading (and possibly writing) CSV files? [closed] 【发布时间】:2010-09-17 01:38:34 【问题描述】:

您能否推荐一个用于读取、解析、验证逗号分隔值 (CSV) 文件中的行并将其映射到 Java 值对象 (JavaBeans) 的 Java 库?

【问题讨论】:

与***.com/questions/101100/csv-api-for-java相关 Super CSV 2.0.0-beta-1 刚刚发布。它包括许多错误修复和新功能(包括 Maven 支持和用于映射嵌套属性和数组/集合的新 Dozer 扩展) 我刚刚在下面添加了一个详细的示例! Apache Commons CSV 是另一种选择。以逗号分隔值 (CSV) 格式和制表符分隔的变体读取和写入文件。 【参考方案1】:

我们用过 http://opencsv.sourceforge.net/ 大获成功

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

【讨论】:

我使用了 opencsv,但在解析数据集中的一些转义字符时失败。我推荐超级 CSV。它更加强大。【参考方案2】:

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

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

读取 CSV 文件

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

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

在 Super CSV 中,您使用简单的字符串数组定义映射 - 数组的每个元素对应于 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 有一个有用的cell processors 库,可用于将字符串从 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 文件等中读取),分隔符和引号字符可通过 preferences (其中有许多预定义的配置可以满足大多数用途)。

下面的代码是不言自明的。

    创建阅读器(使用您的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]]]

更多信息

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

【讨论】:

您应该添加免责声明 嗨@GilbertS,这实际上是第二句话,但我也已经好几年没有从事那个项目了......所以 。除非你的意思是关于从不使用 CSV 的免责声明(我完全可以落后哈哈)。【参考方案3】:

我可以推荐SuperCSV。使用简单,可以满足我的所有需求。

【讨论】:

【参考方案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");

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

最好的问候!

【讨论】:

你是开发者吗?该项目似乎已死。给定代码示例中最具吸引力的方法。 是的,我是开发人员,项目确实很陈旧。我一直在寻找新的维护者:) 如果你没有使用 GPL,我会做一些错误修复,但更商业友好。 @koma 此代码旨在获得 MIT 许可。如果我 gix 这个,你愿意工作吗?我无法继续维护它。 请在 maven central 上发布它【参考方案5】:

我发现Flatpack 非常擅长处理古怪的 CSV 文件(转义、引号、不良记录等)

【讨论】:

【参考方案6】:

之前提出的 CSV File to 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);

除了支持 FLR 和 XML 之外,JSEFA (http://jsefa.sourceforge.net) 似乎也能满足我的所有需求——尤其是绑定到 Java 对象

【讨论】:

【参考方案7】:

我在使用 OpenCSV 从 Java 解析和写入 CSV 文件方面都取得了很好的成功。如果您想使用 Java 读取或编写与 Excel 兼容的电子表格,Apache 的 POI 库是您的最佳选择。

【讨论】:

CVS 是另一回事,但至少链接是正确的...... :-PI 经常在我们自己的代码中看到常见的错字,而且纠正起来很痛苦(在多个地方使用时) ! :-(【参考方案8】:

见CVSBeans

【讨论】:

以上是关于你能推荐一个 Java 库来读取(并且可能写入)CSV 文件吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何从/向流写入/读取位? (C#)

逐行写入文本文件 c

是否有一个好的 C++ 库来读取、创建和修改 BER 编码文件?

你能从部署在 GitHub 上的 heroku 应用程序写入 JSON 文件吗

c - 一个线程写入一个变量,另一个线程读取它

程序打开同一个命名管道并用 C 多次写入