【问题标题】:Unable to Parse Final Column from CSV File using Apache Commons CSV无法使用 Apache Commons CSV 从 CSV 文件中解析最终列
【发布时间】:2019-10-06 15:52:25
【问题描述】:

我有一个包含 19 列的 CSV 文件(最后一列是空的)。我正在通过 Apache Commons CSV 解析文件。当我执行时:

System.out.println("csvRecord.toString() = " + csvRecord.toString());

我得到以下输出:

csvRecord.toString() = CSVRecord [comment=null, mapping={Amount=6, ID=2, UID=4, Address=5, Carrier=17, CPL=14, F=12, GC=13, PIT=9, PP=11, PCIT=10, PT=1, SPI=3, SPI1=8, ST=7, Status=16, SOI=0, TN=18, TP=15}, recordNumber=6, values=[FB, S13 Wood Carving, B07, AG, bis, FB, 44.8, PE, AG XXXXXXX47, UNKNOWN, 39.95, 1.6, 4.1, , -2.2068006148899633, -0.46425251802390777, COMPLETED, US]]

如您所见,最后一列 TN=18(实际上是从 1 计数时的第 19 列)包含在 mapping 部分的 toString() 方法的输出中(但不在 values 部分中) .

但是,当我通过以下代码将csvRecord 转换为映射时:

Map<String, String> csvRecordMap = csvRecord.toMap();

最后一列不再存在。当我执行时:

if (csvRecordMap.containsKey("TN")) 

它返回 false。

根据我的测试,我注意到toMap() 方法不会包含一个空列,如果它后面没有 非空 列(即使该列实际上存在于 CSV 文件中)。如果一列是空的,但后面有非空列,那么它将包含在toMap()方法的返回值中。

如何强制解析器返回所有列——通过toMap() 方法或通过某种方式直接从csvRecord 中提取它,因为它显然存在于toString() 方法中?

谢谢!

【问题讨论】:

    标签: java csv apache-commons


    【解决方案1】:

    循环并添加缺少的名称:

    Map<String, String> map = csvRecord.toMap();
    for (String name : csvParser.getHeaderNames())
        map.putIfAbsent(name, "");
    

    演示

    CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader();
    try (CSVParser csvParser = csvFormat.parse(Files.newBufferedReader(Paths.get("test.txt")))) {
        System.out.println(csvParser.getHeaderNames());
        for (CSVRecord csvRecord : csvParser) {
            System.out.println(csvRecord);
            System.out.println("  toMap(): " + csvRecord.toMap());
    
            Map<String, String> map = csvRecord.toMap();
            for (String name : csvParser.getHeaderNames())
                map.putIfAbsent(name, "");
            System.out.println("  fixed  : " + map);
        }
    }
    

    test.txt

    A,B,C,D
    1,2,3,4
    1,2,3
    1,2
    1
    1,
    1,,
    1,,,
    ,,,4,,,
    

    输出(commons-csv-1.7.jar

    [A, B, C, D]
    CSVRecord [comment='null', recordNumber=1, values=[1, 2, 3, 4]]
      toMap(): {A=1, B=2, C=3, D=4}
      fixed  : {A=1, B=2, C=3, D=4}
    CSVRecord [comment='null', recordNumber=2, values=[1, 2, 3]]
      toMap(): {A=1, B=2, C=3}
      fixed  : {A=1, B=2, C=3, D=}
    CSVRecord [comment='null', recordNumber=3, values=[1, 2]]
      toMap(): {A=1, B=2}
      fixed  : {A=1, B=2, C=, D=}
    CSVRecord [comment='null', recordNumber=4, values=[1]]
      toMap(): {A=1}
      fixed  : {A=1, B=, C=, D=}
    CSVRecord [comment='null', recordNumber=5, values=[1, ]]
      toMap(): {A=1, B=}
      fixed  : {A=1, B=, C=, D=}
    CSVRecord [comment='null', recordNumber=6, values=[1, , ]]
      toMap(): {A=1, B=, C=}
      fixed  : {A=1, B=, C=, D=}
    CSVRecord [comment='null', recordNumber=7, values=[1, , , ]]
      toMap(): {A=1, B=, C=, D=}
      fixed  : {A=1, B=, C=, D=}
    CSVRecord [comment='null', recordNumber=8, values=[, , , 4, , , ]]
      toMap(): {A=, B=, C=, D=4}
      fixed  : {A=, B=, C=, D=4}
    

    【讨论】:

    • 谢谢。有没有办法强制 toMap() 方法包含空列?我怀疑这个问题源于此线程中讨论的类似问题:stackoverflow.com/q/29440357 No?
    • @S.O.S “有没有办法... >
    猜你喜欢
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多