java - 如何在java中保存从不带标题的csv文件中检索的特定数据?

标签 java csv parsing

我正在编写一个应用程序,需要加载一个大型 csv 文件,该文件是纯数据且不包含任何标题。

我正在使用 fastCSV 库来解析文件,但是需要存储数据并需要检索特定字段。由于不需要整个数据,因此我将跳过每三行。 有没有办法在解析文件后设置 header 并将其保存在 ArrayList 等数据结构中?

这是加载文件的函数:

public void fastCsv(String filePath) { 
    File file = new File(filePath);
    CsvReader csvReader = new CsvReader();
    int linecounter = 1;

    try (CsvParser csvParser = csvReader.parse(file, StandardCharsets.UTF_8)) {
        CsvRow row;
        while ((row = csvParser.nextRow()) != null) {
            if ((linecounter % 3) > 0 ) {
            // System.out.println("Read line: " + row);
            //System.out.println("First column of line: " + row.getField(0));
            System.out.println(row);

            }
        linecounter ++;
        }
        System.out.println("Execution Time in ms: " + elapsedTime);
        csvParser.close();
        } catch (IOException e) {
            e.printStackTrace();
    }
}

任何见解将不胜感激。

最佳答案

univocity-parsers支持字段选择并且可以非常轻松地做到这一点。它也比您正在使用的库更快。

以下是如何使用它来选择感兴趣的列:

输入

    String input = "X, X2, Symbol, Date, Open, High, Low, Close, Volume\n" +
            " 5, 9, AAPL, 01-Jan-2015, 110.38, 110.38, 110.38, 110.38, 0\n" +
            " 2710, 289,  AAPL, 01-Jan-2015, 110.38, 110.38, 110.38, 110.38, 0\n" +
            " 5415, 6500, AAPL, 02-Jan-2015, 111.39, 111.44, 107.35, 109.33, 53204600";

配置

    CsvParserSettings settings = new CsvParserSettings(); //many options here, check the tutorial
    settings.setHeaderExtractionEnabled(true); //tells the parser to use the first row as the header row
    settings.selectFields("X", "X2"); //selects the fields 

解析并打印结果

    CsvParser parser = new CsvParser(settings);
    for(String[] row : parser.iterate(new StringReader(input))){
        System.out.println(Arrays.toString(row));
    }
}

输出

[5, 9]
[2710, 289]
[5415, 6500]

在字段选择上,您可以使用任何字段序列,并且具有不同列大小的行,解析器将很好地处理这个问题。无需编写复杂的逻辑来处理该问题。

在代码中处理文件,更改上面的示例来执行此操作:

    for(String[] row : parser.iterate(new File(filePath))){
         ... //your logic goes here.
    }

如果您想要更可用的记录(带有键入的值),请改用此:

    for(Record record : parser.iterateRecords(new File(filePath))){
         ... //your logic goes here.
    }

加速

处理文件的最快方法是通过RowProcessor。这是一个接收从输入解析的行的回调:

settings.setProcessor(new AbstractRowProcessor() {
    @Override
    public void rowProcessed(String[] row, ParsingContext context) {
        System.out.println(Arrays.toString(row));
        context.skipLines(3); //use the context object to control the parser
    }
});

CsvParser parser = new CsvParser(settings);
//`parse` doesn't return anything. Rows go to the `rowProcessed` method.
parser.parse(new StringReader(input)); 

您应该能够快速解析非常大的文件。如果速度变慢,请查看代码(避免向内存中的列表或集合添加值,或者至少将集合预先分配到合适的大小,并使用 Xms 和 Xmx 标志为 JVM 提供大量内存来使用)。

现在这个解析器是您能找到的最快的。我做了这个performance comparison前段时间你可以引用一下。

希望这有帮助

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

关于java - 如何在java中保存从不带标题的csv文件中检索的特定数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54733879/

相关文章:

java - maven:执行而不实际构建任何东西

ruby-on-rails - 导入 - csv 到 activerecord - Rails 中的错误处理

c++ - 如何使用 boost::spirit 解析 csv

c# - Json解析C#

c# - 如何从包含 XMl 的字符串中获取内部 xml

php - 无法在 PHP 文件中包含/执行 CGI 文件

java - Thymeleaf 自定义方言不起作用

java - JButton settext具体位置

python - 将 pandas DataFrame 列附加到 CSV

java - 比较两个对象引用的常见情况