Java - 使用Apache.commons.csv编写CSV文件

13

我在Java中使用apache.commons.csv库。我正在使用以下代码从网页读取CSV文件:

InputStream input = new URL(url).openStream();
        Reader reader = new InputStreamReader(input, "UTF-8");

        defaultParser = new CSVParser(reader, CSVFormat.DEFAULT);
        excelParser = new CSVParser(reader, CSVFormat.EXCEL.withHeader()); 

        defaultParsedData = defaultParser.getRecords();
        excelParsedData = excelParser.getRecords();

然而,我在这个库中找不到一种方法可以轻松地将此文件写入我的计算机,以便稍后打开并从中读取。

我尝试了这段代码来保存文件。

String outputFile = savePath+".csv";
        CSVPrinter csvFilePrinter = null;
        CSVFormat csvFileFormat = CSVFormat.EXCEL.withHeader();
        FileWriter fileWriter = new FileWriter(outputFile);
        csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat);

        for (CSVRecord csvRecord : excelParser) {
            for(String dataPoint: csvRecord){
                csvFilePrinter.print(dataPoint);
            }
            csvFilePrinter.print('\n');
         }

        fileWriter.flush();
        fileWriter.close();
        csvFilePrinter.close();

然而,当我使用这段代码尝试读取文件时,什么都没有输出:

InputStream input = new FileInputStream(cvsFilePath);
        Reader reader = new InputStreamReader(input, "UTF-8");

        CSVParser load = new CSVParser(reader, CSVFormat.EXCEL);
        //TEST THAT IT WORKED
        java.util.List<CSVRecord> testlist = load.getRecords();
        CSVRecord dataPoint = testlist.get(0);
        System.out.println("print: " + dataPoint.get(0));
这仅仅打印出 "print: "。如果我添加

System.out.println("print: " + dataPoint.get(1));

它产生了一个

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

当我用记事本打开保存的CSV文件时,会有一个空行,然后是:

2016-03-04,714.98999,716.48999,706.02002,710.890015,1967900,710.890015," ",2016-03-03,718.679993,719.450012,706.02002,712.419983,1956800,712.419983," ",2016-03-02,719.00,720.00,712.00,718.849976,1627800,718.849976,"


“写入数据失败”是什么意思? - Arnaud
@Berger 嗯,我确定我没有正确编写代码。保存的文件与从网页读取的文件不同。我想应该有一个简单内置的方法在Apache Commons中保存从解析器获取的文件,但是我找不到一个,所以我尝试了这种方法。 - jonbon
你能展示一下一个样例输入和输出结果吗? - Arnaud
@Berger 当我尝试在Excel中打开文件时,出现“文件未完全加载”的错误。我已更新原始帖子,其中包含我用于从保存的文件中读取的代码。 - jonbon
用一个简单的文本编辑器(记事本,等等)打开它,并将内容粘贴到你的问题中。 - Arnaud
@Berger 我添加了在将保存的文件加载到程序中时遇到的问题。我即将添加在记事本中的显示效果。 - jonbon
3个回答

16

看起来你是在同一行上打印所有记录。

使用printRecords等其他方法将更有帮助:

String outputFile = savePath+".csv";
CSVPrinter csvFilePrinter = null;
CSVFormat csvFileFormat = CSVFormat.EXCEL.withHeader();
FileWriter fileWriter = new FileWriter(outputFile);
csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat);

csvFilePrinter.printRecords(excelParser.getRecords());


fileWriter.flush();
fileWriter.close();
csvFilePrinter.close();

8

Arnaud的回答是正确且好的。这里有一个更短、更现代的变体。

在这里我们:

使用现代Java提供的PathFileFiles类来更轻松地处理文件。
使用BufferedWriter以获得更好的大数据量性能。
指定要使用的字符编码。通常UTF-8是最好的。如果您不理解,请阅读此内容
为文件相关异常添加必要的try-catches
添加try-with-resources语法以自动关闭文件。
跳过显式刷新,因为缓冲写入器将作为自动关闭BufferedWriterCSVPrinter的一部分自动刷新。引用Javadoc的话,调用java.io.Writer::close “关闭流并先刷新它”。

代码:

CSVFormat format = CSVFormat.EXCEL.withHeader();
Path path = Paths.get( savePath + ".csv" );
try (
        BufferedWriter writer = Files.newBufferedWriter( path , StandardCharsets.UTF_8 ) ;
        CSVPrinter printer = new CSVPrinter( writer , format ) ;
)
{
    printer.printRecords( excelParser.getRecords() );
} catch ( IOException e )
{
    e.printStackTrace();
}

编辑:缺少一个括号。


2
你尝试过刷新并关闭CSVPrinter,而不是FileWriter吗?

2
我没有关闭CSVPrinter,谢谢@ionFreeman。 - katwekibs
不用谢! - Ion Freeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接