【问题标题】:How to merge CSV files in Java如何在 Java 中合并 CSV 文件
【发布时间】:2011-03-19 10:27:55
【问题描述】:

我的第一个 CSV 文件看起来像这样,其中包含标题(标题仅包含在顶部,而不是每个条目之后):

NAME,SURNAME,AGE
Fred,Krueger,Unknown
.... n records

我的第二个文件可能如下所示:

NAME,MIDDLENAME,SURNAME,AGE
Jason,Noname,Scarry,16
.... n records with this header template

合并后的文件应如下所示:

NAME,SURNAME,AGE,MIDDLENAME
Fred,Krueger,Unknown,
Jason,Scarry,16,Noname
....

基本上如果标题不匹配,所有新的标题标题(列)都应该按照该顺序添加到原始标题及其值之后。

更新

上面的 CSV 变得更小了,所以我可以说明我想要实现的目标,实际上 CSV 文件是在此(合并)之前的一步生成的,最多可以有 100 列

我该怎么做?

【问题讨论】:

标签: java csv


【解决方案1】:

我将为“更大”格式创建一个模型(一个具有四个字段的简单类和一个用于此类实例的集合)并实现两个解析器,一个用于第一个模型,一个用于第二个模型。为两个 csv 文件的所有行创建记录,并实现编写器以正确格式输出 csv。简而言之:

 public void convert(File output, File...input) {

   List<Record> records = new ArrayList<Record>();
   for (File file:input) {
     if (input.isThreeColumnFormat()) {
        records.addAll(ThreeColumnFormatParser.parse(file));
     } else {
        records.addAll(FourColumnFormatParser.parse(file));
     }
   }
   CsvWriter.write(output, records);
 }

从你的评论中我看到,你有很多不同的 csv 格式和一些共同的列。

您可以为各种 csv 文件中的任何行定义模型,如下所示:

public class Record {
  Object id; // some sort of unique identifier
  Map<String, String> values; // all key/values of a single row
  public Record(Object id) {this.id=id;}
  public void put(String key, String value){
    values.put(key, value);
  }
  public void get(String key) {
    values.get(key);
  }
}

要解析任何文件,您首先要读取标题并将列标题添加到全局密钥库(稍后将需要用于输出),然后为所有行创建记录,例如:

//...
List<Record> records = new ArrayList<Record>()

for (File file:getAllFiles()) {
  List<String> keys = getColumnsHeaders(file);
  KeyStore.addAll(keys);  // the store is a Set
  for (String line:file.getLines()) {
    String[] values = line.split(DELIMITER);
    Record record = new Record(file.getName()+i);  // as an example for id
    for (int i = 0; i < values.length; i++) {
      record.put(keys.get(i), values[i]);
    }
    records.add(record);
  }
}
// ...

现在密钥库已经使用了所有列标题名称,我们可以遍历所有记录的集合,获取所有键的所有值(如果该记录的文件没有使用该键,则获取 null),组装csv 行并将所有内容写入一个新文件。

【讨论】:

  • 感谢您的回复,我的问题中的 csv 只是我想要实现的目标的示例,CSV 文件和之前生成的一个步骤,并且可以有从 20 到 100 的许多列跨度>
【解决方案2】:

读入第一个文件的标题并创建列名列表。现在读取第二个文件的标题并将列表中不存在的任何列名添加到列表的末尾。现在您已经按照您想要的顺序排列了列,您可以先将其写入新文件。

接下来我将解析每个文件,并为每一行创建一个列名到值的映射。一旦解析了行,您就可以遍历新的列名列表并从映射中提取值并将它们立即写入新文件。如果值为 null,则不打印任何内容(如果需要,只需一个逗号)。

可能有更有效的解决方案可用,但我认为这符合您提出的要求。

【讨论】:

    【解决方案3】:

    试试这个:

    http://ondra.zizka.cz/stranky/programovani/ruzne/querying-transforming-csv-using-sql.texy

    crunch input.csv output.csv "SELECT AVG(duration) AS durAvg FROM (SELECT * FROM indata ORDER BY duration LIMIT 2 OFFSET 6)"
    

    【讨论】:

      猜你喜欢
      • 2016-01-26
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 2011-01-31
      • 2011-01-26
      • 2013-06-19
      • 1970-01-01
      相关资源
      最近更新 更多