Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用supercsv跳过纯空白行和具有可变列的行_Java_Csv_Opencsv_Supercsv - Fatal编程技术网

Java 如何使用supercsv跳过纯空白行和具有可变列的行

Java 如何使用supercsv跳过纯空白行和具有可变列的行,java,csv,opencsv,supercsv,Java,Csv,Opencsv,Supercsv,我正在研究CSV解析器需求,并且正在使用supercsv解析器库。我的CSV文件可以有25列(由制表符(|)分隔)和最多100k行(带有附加标题行) 我想忽略只有空格的行和包含少于25列的行 我使用带有名称映射的IcvBeanReader(将csv值设置为pojo)和字段处理器(处理验证)来读取文件 我假设Supercsv IcvBeanReader默认情况下会跳过空白行。但是如果一行包含的列数少于25个,该如何处理呢?(1)如果必须由Java程序使用Super-CSV进行选择,那么(我引述)“

我正在研究CSV解析器需求,并且正在使用supercsv解析器库。我的CSV文件可以有25列(由制表符(|)分隔)和最多100k行(带有附加标题行)

我想忽略只有空格的行和包含少于25列的行

我使用带有名称映射的IcvBeanReader(将csv值设置为pojo)和字段处理器(处理验证)来读取文件

我假设Supercsv IcvBeanReader默认情况下会跳过空白行。但是如果一行包含的列数少于25个,该如何处理呢?

(1)如果必须由Java程序使用
Super-CSV
进行选择,那么(我引述)“您必须使用CsvListReader”。特别是:listReader.length()

有关详细信息,请参阅

(2)如果您可以通过预处理CSV文件来执行选择,那么您可能希望考虑一个合适的命令行工具(或工具,取决于CSV格式的复杂性)。如果CSV文件的分隔符没有出现在任何字段中,那么awk就足够了。例如,如果满足假设,并且分隔符为

|
,则相关的awk筛选器可以简单如下:

awk -F'|' 'NF == 25 {print}'

如果CSV文件格式对于awk的简单应用程序来说过于复杂,那么您可能希望将复杂的格式转换为更简单的格式;TSV通常有很多建议。

您可以通过编写自己的标记器轻松做到这一点

例如,以下标记器将具有与默认标记器相同的行为,但将跳过任何列数不正确的行

public class SkipBadColumnCountTokenizer extends Tokenizer {

    private final int expectedColumns;

    private final List<Integer> ignoredLines = new ArrayList<>();

    public SkipBadColumnCountTokenizer(Reader reader, 
            CsvPreference preferences, int expectedColumns) {
        super(reader, preferences);
        this.expectedColumns = expectedColumns;
    }

    @Override
    public boolean readColumns(List<String> columns) throws IOException {
        boolean moreInputExists;
        while ((moreInputExists = super.readColumns(columns)) && 
            columns.size() != this.expectedColumns){
            System.out.println(String.format("Ignoring line %s with %d columns: %s", getLineNumber(), columns.size(), getUntokenizedRow()));
            ignoredLines.add(getLineNumber());
        }

        return moreInputExists;

    }

    public List<Integer> getIgnoredLines(){
        return this.ignoredLines;
    }
}
打印以下输出(注意它是如何跳过所有无效行的):


什么是10万?为什么要写单词选项卡而不是管道字符(|)?这看起来像是的一个更简单的版本,但是您没有阅读包含错误列的行,而是忽略了它们。非常感谢。它工作正常,int-expectedColumns=25;Tokenizer Tokenizer=new SkipBadColumnCountTokenizer(新文件读取器(文件),新CsvPreference.Builder(““”,“|“,“\n”).build(),expectedColumns);beanReader=new CsvBeanReader(Tokenizer,新CsvPreference.Builder(“”,“|“,“\n”).build());有没有办法捕获包含坏列的行号?当然,您可以在标记器中调用
getLineNumber()
——记录它或将它收集到列表中,并在最后检索它。我已经更新了上面的示例以演示日志记录。再次感谢。此方法返回boolean及其重写的标记器方法。请您帮助我们如何将这些错误列记录到列表中。我需要在TestInvalidRows(您已经在上面写过)类级别上拥有该列表。再次感谢您的支持,因为在其他帖子中查看了您的自定义CSV异常处理程序后..我成功地处理了字段级验证错误,而没有抛出异常。不用担心,我刚刚更新了示例标记器,以演示捕获行号的一种方法。感谢您在这方面的支持:)
@Test
public void testInvalidRows() throws IOException {

    String input = "column1,column2,column3\n" +
            "has,three,columns\n" +
            "only,two\n" +
            "one\n" +
            "three,columns,again\n" +
            "one,too,many,columns";

    CsvPreference preference = CsvPreference.EXCEL_PREFERENCE;
    int expectedColumns = 3;
    SkipBadColumnCountTokenizer tokenizer = new SkipBadColumnCountTokenizer(
        new StringReader(input), preference, expectedColumns);

    try (ICsvBeanReader beanReader = new CsvBeanReader(tokenizer, preference)) {
        String[] header = beanReader.getHeader(true);
        TestBean bean;
        while ((bean = beanReader.read(TestBean.class, header)) != null){
            System.out.println(bean);
        }
        System.out.println(String.format("Ignored lines: %s", tokenizer.getIgnoredLines()));
    }

}
TestBean{column1='has', column2='three', column3='columns'}
Ignoring line 3 with 2 columns: only,two
Ignoring line 4 with 1 columns: one
TestBean{column1='three', column2='columns', column3='again'}
Ignoring line 6 with 4 columns: one,too,many,columns
Ignored lines: [3, 4, 6]