首页 > 解决方案 > 如何在向文件中添加更多行时动态添加 CSV 标题

问题描述

客户向我发送了我需要附加到带有 headers 的 CSV 文件的键值对列表。

lang=java                           lang, version, maven
version=1.8              ----->     java, 1.8, true
maven=true

另一个输入可能是:

lang=C#                           lang, version, maven
version=7.2              ----->   java, 1.8, true
maven=false                       C#, 7.2, false  

列表的数量可能有几百万,因此我需要将数据刷新到磁盘并且不能将其全部保存在内存中。

由于键列表由客户端确定,因此我使用他的第一个输入来确定 CSV 文件的标题:

org.apache.commons.csv.CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(x, y, z ...)));

并从那时起仅附加相关列的值:

csvPrinter.printRecord(xValue, yValue, zValue.....)

然而,它是一个顽皮的客户,有时他会发送我从未见过的新密钥:

lang=java
meetMeAt=London
version=1.4
maven=false

在这一点上,我如何向 CSV 添加另一个标题?

首先将所有列表保存到没有标题的 csv 文件中,将所有标题累积在程序内存中,然后创建另一个包含所有标题的文件并将第一个文件中的记录复制到其中?合理吗?

标签: javacsvapache-commons

解决方案


您提出的解决方案有一个问题需要我们解决:

lang=java                           java, 1.8, true
version=1.8              ----->     
maven=true

lang=java                           java, 1.8, true
version=1.8              ----->           ???
gradle=true

你想如何表达它?添加另一列?当您不知道列标题时,您如何知道需要添加另一列?

如果您有能力读取两次输入,我建议您在第一次读取时收集标题,然后使用已知的列标题和位置重新读取。

如果您只需要读取一次输入,您的想法可以这样工作:

  • 将标题和相应的列位置保留在内存中
  • 编写不带标题的 CSV,但将所有数据放在正确的列中
    • 请注意,列数可能会增加,第一行的列数少于最后一行
  • 完成原始输入后,重新编写输出 CSV:
    • 将标题放在第一行
    • 将缺失的列添加到比最终列数短的所有行

推荐阅读