【问题标题】:CSV API for Java [closed]Java的CSV API [关闭]
【发布时间】:2010-09-11 04:40:18
【问题描述】:

谁能推荐一个简单的 API,让我可以使用读取 CSV 输入文件,进行一些简单的转换,然后编写它。

快速 google 发现 http://flatpack.sourceforge.net/ 看起来很有希望。

我只是想在将自己耦合到此 API 之前检查其他人正在使用什么。

【问题讨论】:

标签: java csv


【解决方案1】:

Apache Commons CSV

查看Apache Common CSV

这个库读写several variations of CSV,包括标准的RFC 4180。还读取/写入Tab-delimited 文件。

  • Excel
  • Informix 卸载
  • InformixUnloadCsv
  • MySQL
  • 甲骨文
  • PostgreSQLCsv
  • PostgreSQLText
  • RFC4180
  • TDF

【讨论】:

  • 我使用沙盒 Commons CSV 已经有一段时间了,从未遇到过问题。我真的希望他们将其推广到完全地位并将其从沙盒中移除。
  • @bmatthews68 沙盒链接已失效 - 看起来它已移至 apache commons proper(我也在答案中编辑了链接)
【解决方案2】:

阅读 CSV 格式描述让我觉得使用 3rd 方库比自己编写更容易:

维基百科列出了 10 个或一些已知的库:

我使用某种检查列表比较了列出的库。 OpenCSV 对我来说是赢家 (YMMV),结果如下:

+ maven

+ maven - release version   // had some cryptic issues at _Hudson_ with snapshot references => prefer to be on a safe side

+ code examples

+ open source   // as in "can hack myself if needed"

+ understandable javadoc   // as opposed to eg javadocs of _genjava gj-csv_

+ compact API   // YAGNI (note *flatpack* seems to have much richer API than OpenCSV)

- reference to specification used   // I really like it when people can explain what they're doing

- reference to _RFC 4180_ support   // would qualify as simplest form of specification to me

- releases changelog   // absence is quite a pity, given how simple it'd be to get with maven-changes-plugin   // _flatpack_, for comparison, has quite helpful changelog

+ bug tracking

+ active   // as in "can submit a bug and expect a fixed release soon"

+ positive feedback   // Recommended By 51 users at sourceforge (as of now)

【讨论】:

    【解决方案3】:

    更新:此答案中的代码适用于 Super CSV 1.52。 Super CSV 2.4.0 的更新代码示例可以在项目网站上找到: http://super-csv.github.io/super-csv/index.html


    SuperCSV 项目直接支持 CSV 单元格的解析和结构化操作。从http://super-csv.github.io/super-csv/examples_reading.html 你会发现例如

    给定一个班级

    public class UserBean {
        String username, password, street, town;
        int zip;
    
        public String getPassword() { return password; }
        public String getStreet() { return street; }
        public String getTown() { return town; }
        public String getUsername() { return username; }
        public int getZip() { return zip; }
        public void setPassword(String password) { this.password = password; }
        public void setStreet(String street) { this.street = street; }
        public void setTown(String town) { this.town = town; }
        public void setUsername(String username) { this.username = username; }
        public void setZip(int zip) { this.zip = zip; }
    }
    

    并且您有一个带有标题的 CSV 文件。我们假设以下内容

    username, password,   date,        zip,  town
    Klaus,    qwexyKiks,  17/1/2007,   1111, New York
    Oufu,     bobilop,    10/10/2007,  4555, New York
    

    然后您可以创建 UserBean 的实例,并使用以下代码从文件第二行中的值填充它

    class ReadingObjects {
      public static void main(String[] args) throws Exception{
        ICsvBeanReader inFile = new CsvBeanReader(new FileReader("foo.csv"), CsvPreference.EXCEL_PREFERENCE);
        try {
          final String[] header = inFile.getCSVHeader(true);
          UserBean user;
          while( (user = inFile.read(UserBean.class, header, processors)) != null) {
            System.out.println(user.getZip());
          }
        } finally {
          inFile.close();
        }
      }
    }
    

    使用以下“操作规范”

    final CellProcessor[] processors = new CellProcessor[] {
        new Unique(new StrMinMax(5, 20)),
        new StrMinMax(8, 35),
        new ParseDate("dd/MM/yyyy"),
        new Optional(new ParseInt()),
        null
    };
    

    【讨论】:

    • 您的代码无法编译,因此我提交了一些更正。此外, ParseDate() 无法正常工作,因此我将其替换为读取字符串。可以稍后解析。
    • 很大的限制:SuperCSV 不是线程安全的,我打算看看 Jackson,虽然它可能功能更有限
    • SuperCsv 也不允许使用多图。很高兴看到它与 MultiMaps 一起使用。
    【解决方案4】:

    CSV 格式对于 StringTokenizer 来说听起来很简单,但它可能会变得更加复杂。 在德国,分号用作分隔符,包含分隔符的单元格需要转义。你不会用 StringTokenizer 轻松处理这个问题。

    我会选择http://sourceforge.net/projects/javacsv

    【讨论】:

      【解决方案5】:

      您可以使用 csvreader api 并从以下位置下载:

      http://sourceforge.net/projects/javacsv/files/JavaCsv/JavaCsv%202.1/javacsv2.1.zip/download

      http://sourceforge.net/projects/javacsv/

      使用以下代码:

      / ************ For Reading ***************/
      
      import java.io.FileNotFoundException;
      import java.io.IOException;
      
      import com.csvreader.CsvReader;
      
      public class CsvReaderExample {
      
          public static void main(String[] args) {
              try {
      
                  CsvReader products = new CsvReader("products.csv");
      
                  products.readHeaders();
      
                  while (products.readRecord())
                  {
                      String productID = products.get("ProductID");
                      String productName = products.get("ProductName");
                      String supplierID = products.get("SupplierID");
                      String categoryID = products.get("CategoryID");
                      String quantityPerUnit = products.get("QuantityPerUnit");
                      String unitPrice = products.get("UnitPrice");
                      String unitsInStock = products.get("UnitsInStock");
                      String unitsOnOrder = products.get("UnitsOnOrder");
                      String reorderLevel = products.get("ReorderLevel");
                      String discontinued = products.get("Discontinued");
      
                      // perform program logic here
                      System.out.println(productID + ":" + productName);
                  }
      
                  products.close();
      
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
          }
      
      }
      

      写入/追加到 CSV 文件

      代码:

      /************* For Writing ***************************/
      
      import java.io.File;
      import java.io.FileWriter;
      import java.io.IOException;
      
      import com.csvreader.CsvWriter;
      
      public class CsvWriterAppendExample {
      
          public static void main(String[] args) {
      
              String outputFile = "users.csv";
      
              // before we open the file check to see if it already exists
              boolean alreadyExists = new File(outputFile).exists();
      
              try {
                  // use FileWriter constructor that specifies open for appending
                  CsvWriter csvOutput = new CsvWriter(new FileWriter(outputFile, true), ',');
      
                  // if the file didn't already exist then we need to write out the header line
                  if (!alreadyExists)
                  {
                      csvOutput.write("id");
                      csvOutput.write("name");
                      csvOutput.endRecord();
                  }
                  // else assume that the file already has the correct header line
      
                  // write out a few records
                  csvOutput.write("1");
                  csvOutput.write("Bruce");
                  csvOutput.endRecord();
      
                  csvOutput.write("2");
                  csvOutput.write("John");
                  csvOutput.endRecord();
      
                  csvOutput.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
          }
      }
      

      【讨论】:

        【解决方案6】:

        还有CSV/Excel Utility。它假定所有这些数据都是表状的,并从迭代器中传递数据。

        【讨论】:

          【解决方案7】:

          我过去使用过OpenCSV

          import au.com.bytecode.opencsv.CSVReader;

          字符串文件名 = "data.csv";
          CSVReader reader = new CSVReader(new FileReader(fileName));
          
          

          // 如果第一行是标题 String[] header = reader.readNext();
          // 遍历 reader.readNext 直到它返回 null String[] line = reader.readNext();

          another question 的答案还有一些其他选择。

          【讨论】:

          • 不幸的是,OpenCSV 的最新下载(评论时为 v2.2)无法编译,并且它们不提供预构建的二进制文件。
          • 我从 SourceForge 下载的包在 deploy 文件夹中有一个二进制文件。
          • 如果您使用的是maven,请注意官网的依赖代码包含版本声明“2.0”,其中存在一些错误,但在repositories中更新了2.3版本。
          • 这个库不会在单独的线程中写入文件,不是吗?
          • 根据github.com/uniVocity/csv-parsers-comparison,平均比 uniVocity 慢 73%..
          【解决方案8】:

          如果您打算从 excel 中读取 csv,那么有一些有趣的极端情况。我不记得所有这些,但是 apache commons csv 无法正确处理它(例如,使用 url)。

          请务必使用引号、逗号和斜杠测试 excel 输出。

          【讨论】:

          【解决方案9】:

          对于我工作的最后一个需要处理大量 CSV 的企业应用程序——几个月前——我在 sourceforge 使用了SuperCSV,发现它简单、健壮且没有问题。

          【讨论】:

          • +1 用于 SuperCSV,但它有一些尚未修复的令人讨厌的错误,目前尚未处理新错误,最后一个版本已经快两年了。但是我们在生产中使用了一个补丁/修改版本,没有任何问题。
          • @MRalwasser Super CSV 2.0.0-beta-1 最近已发布。它包括许多错误修复和新功能(包括 Maven 支持和用于映射嵌套属性和数组/集合的新 Dozer 扩展)
          • @Hound-Dog 谢谢你的更新,我已经注意到了新的测试版,我很高兴看到这个项目还活着——尽管提交的频率仍然让我有点担心(几乎所有的提交仅几天)。但我会看看。有最终 2.0 的预计发布日期吗?
          • @MRalwasser 我是目前唯一的开发人员并且有全职工作,所以每当我有空闲的周末时,我都倾向于在这方面工作 - 因此零星提交:) 近 1000 SF 下载现在是测试版,没有错误,因此有望在下月初发布最终版本。如果您对未来的功能有任何想法,请告诉我们。
          • SuperCSV 在这个阶段不是线程安全的,这使得它不是很健壮恕我直言
          【解决方案10】:

          我们使用JavaCSV,效果很好

          【讨论】:

          • 这个库的唯一问题是,当不在 Windows 上运行时,它不允许您使用 Windows 行终止符 (\r\n) 输出 CSV 文件。作者多年未提供支持。我不得不分叉它以允许缺少的功能:JavaCSV 2.2
          猜你喜欢
          • 1970-01-01
          • 2012-03-05
          • 1970-01-01
          • 2015-07-24
          • 1970-01-01
          • 2013-06-12
          • 1970-01-01
          相关资源
          最近更新 更多