【问题标题】:Apache common CSVParser/CSVRecord to return null for empty fieldsApache 通用 CSVParser/CSVRecord 为空字段返回 null
【发布时间】:2016-04-16 12:07:25
【问题描述】:

全部

我有一个关于 Apache 通用 CSVParser/CSVRecord 的问题。看看下面的 CSV 文件:

Header1,Header2,Header3
"",,"L1C3"

CSVParser/CSVRecord 为前两列返回“”。就我而言,我想区分空字符串(“”)和空值。是否可以设置让 CSVParser 为第二列返回 null 的配置?

谢谢。

【问题讨论】:

  • 我不确定这是否是一个骗局,虽然我也看到了另一篇文章。
  • @TimBiegeleisen 是的。你可以看到完全相同的问题。
  • 同样的问题,不同的图书馆,还是没有?
  • 一个技巧是预处理您的文件并用其他东西替换您的“”。然后你可以在CVSFormat上使用withNullString

标签: java csv


【解决方案1】:

我用过这种格式:

CSVFormat.RFC4180.withFirstRecordAsHeader()
   .withIgnoreSurroundingSpaces()
   .withNullString("")

其中 2 种配置:

  1. 忽略空格 - 修剪两边的任何值,如果都是空格,则将其修剪为空白空间
  2. null string - 将空格视为 null

这是一个示例用法:

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import org.junit.Test;

public class CsvParseTest {

    @Test
    public void testParseWillTrimAndConvertToNull() throws Exception {
        String CSV_HEADER = "Name,MobileNo,Location";
        String CSV_ROW_1 = "abc,   ,australia"; // MobileNo is 3 whitespaces
        CSVParser parse = CSVFormat.RFC4180.withFirstRecordAsHeader().withIgnoreSurroundingSpaces().withNullString("")
                .parse(new BufferedReader(new StringReader(CSV_HEADER + "\n" + CSV_ROW_1)));

        CsvRecord rec = parse.getRecords().get(0);
        assertEquals("abc", rec.get("Name"));
        assertNull(rec.get("MobileNo"));
        assertEquals("australia", rec.get("Location"));
    }
}

【讨论】:

    【解决方案2】:

    我认为 uniVocity-parsers 是唯一允许您区分空字符串和空字符串的库(我知道这不会直接解决您使用 Apache Commons CSV 的问题,但至少有一种方法可以让您获得需要)。

    这是怎么做的:

    public static void main(String ... args){
        String input = "Header1,Header2,Header3\n" +
                "\"\",,\"L1C3\"";
    
        CsvParserSettings settings = new CsvParserSettings(); //many options here, check the tutorial.
        settings.setEmptyValue("I'm empty"); //value to use when the parser finds "". Set to "" to get an empty String.
        settings.setNullValue("I'm null"); //value to use when the parser finds a null value (i.e. ,,). 
    
        CsvParser parser = new CsvParser(settings);
        List<String[]> allRows = parser.parseAll(new StringReader(input));
    
        for(String[] row : allRows){
            System.out.println(Arrays.toString(row));
        }
    }
    

    这将产生以下输出:

    [Header1, Header2, Header3]
    [I'm empty, I'm null, L1C3]
    

    uniVocity-parsers 的速度也比 Apache Commons CSV 快 3 倍,并且具有更多功能。

    披露:我是这个库的作者。它是开源免费的(Apache V2.0 许可)。

    【讨论】:

      【解决方案3】:

      最后,我没有找到使用 Apache Commons CSV 库返回 null 的好解决方案。我切换到 OpenCSV 3.6,这是我使用的代码,我也在 another thread 上发布了它。感谢所有建议 OpenCSV 的人。

      CSVReaderBuilder 有 withFieldAsNull() 用于此目的。

      CSVReader csvReader = new CSVReaderBuilder(csvFileReader)
          .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
          .build();
      

      【讨论】:

        【解决方案4】:

        在 Apache commons csv 1.2 中,我们可以使用 CSVFormat 类方法 withNullString() 将空字符串转换为 NULL。根据您的要求,这里的空字符串可以是"""N/A""Nill"

        CSVFormat csvFormat = CSVFormat.DEFAULT.withNullString("");
        CSVParser csvParser = new CSVParser(fileReader, csvFormat);
        

        这将为有问题的给定记录提供NULL, NULL, L1C3

        注意:空记录会自动转换为空字符串,从而最终转换为NULL值。

        【讨论】:

          猜你喜欢
          • 2018-09-26
          • 2018-11-09
          • 2021-08-06
          • 1970-01-01
          • 1970-01-01
          • 2021-11-27
          • 2021-10-24
          • 2021-10-29
          • 1970-01-01
          相关资源
          最近更新 更多