【问题标题】:Export to .csv using java does not output file使用java导出到.csv不输出文件
【发布时间】:2019-06-19 21:05:36
【问题描述】:

我正在尝试将 JTable 的内容导出到 .csv 文件。我尝试了一些代码,没有错误,但是我打算编写的文件没有被写入。谁能明白为什么?谢谢

public static boolean exportToCSV(JTable resultsTable) {
   try {

    TableModel model = resultsTable.getModel();
    FileWriter csv = new FileWriter(new File("/tmp/export.csv"));

    for (int i = 0; i < model.getColumnCount(); i++) {
        csv.write(model.getColumnName(i) + ",");
    }

    csv.write("\n");

    for (int i = 0; i < model.getRowCount(); i++) {
        for (int j = 0; j < model.getColumnCount(); j++) {
            csv.write(model.getValueAt(i, j).toString() + ",");
        }
        csv.write("\n");
    }

    csv.close();
    return true;
   } catch (IOException e) {
    e.printStackTrace();
   }
   return false;
}

【问题讨论】:

  • 发帖前搜索 Stack Overflow。写入文件和写入 CSV 已被多次介绍,并提供完整的代码示例供您学习。提示:使用 Apache Commons CSV 等库。
  • 您是否收到任何错误消息?看起来您正在写信给/tmp,据我了解,不能保证/tmp 中的文件会保留很长时间。
  • 如果可以,您应该始终使用外部库来创建 csv 文件(因为您需要转义某些字符)。但是,在这种情况下,您似乎无法写入与 csv 无关的文件

标签: java export-to-csv


【解决方案1】:

用一个简单的文件练习

迈出小步。首先,请确保您已成功打开文件。

现代 Java 提供了 PathFileFiles 类,可以更轻松地处理存储中的文件。

例子:

package work.basil.example;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Csver
{
    public static void main ( String[] args )
    {
        Csver app = new Csver() ;
        app.writeDummyFile() ;
    }

    private void writeDummyFile ()
    {
        Path path = Paths.get( "/Users/basilbourque/dummy.txt" ) ;
        // Use try-with-resources to auto-close the file if successfully opened.
        try ( 
            BufferedWriter writer = Files.newBufferedWriter( path ) ;  // Will be automatically closed if successfully opened.
        )
        {
            writer.write( "Bonjour le monde!" ) ;
        } catch ( IOException e )
        {
            e.printStackTrace() ;
        }
    }

}

使用 CSV 库

接下来,对于 CSV 或制表符分隔的文件等,请使用库。我使用Apache Commons CSV。在 Stack Overflow 上搜索许多使用此库和其他此类库来读取和写入此类文件的示例。

使用CSVFormat 定义文件类型。这里我们使用RFC 4180 定义的标准CSV。请注意,标准 CSV 使用 CRLF(回车换行符)来表示换行符,而不是在类 Unix 平台中常见的 LF(换行符)。

打开文件时,我们指定UTF-8字符编码。 UTF-8 通常是最好使用的编码;它涵盖了所有 Unicode 字符,并且是 US-ASCII 的超集。

CSVPrinter::print 方法在输出一行时一次添加一个字段。我们通过调用CSVPrinter::println 来终止该行。

我将您的 ij 变量重命名为有意义。

我在文件顶部添加了列名。您可能希望保留或放弃该功能,由您自己决定。

注意我们如何使用 try-with-resources 语法来自动关闭我们的文件。

package work.basil.example;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;

import javax.swing.*;
import javax.swing.table.TableModel;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Csver
{
    public static void main ( String[] args )
    {
        Csver app = new Csver();

        // Practice writing a simple file.
        app.writeDummyFile();

        // Write out the data in a JTable to standard CSV file.
        JTable jtable = app.newJTable();
        app.writeCSV( jtable.getModel() );

        System.out.println( "« fin »" );
    }

    private void writeCSV ( final TableModel model )
    {
        CSVFormat format = CSVFormat.RFC4180;
        Path path = Paths.get( "/Users/basilbourque/animals.csv" );
        try (
                BufferedWriter writer = Files.newBufferedWriter( path , StandardCharsets.UTF_8 ) ;
                CSVPrinter printer = new CSVPrinter( writer , format ) ;
        )
        {
            // Print column headers, if you want.
            for ( int columnIndex = 0 ; columnIndex < model.getColumnCount() ; columnIndex++ )
            {
                printer.print( model.getColumnName( columnIndex ) );
            }
            printer.println();

            // Print rows.
            for ( int rowIndex = 0 ; rowIndex < model.getRowCount() ; rowIndex++ )
            {
                for ( int columnIndex = 0 ; columnIndex < model.getColumnCount() ; columnIndex++ )
                {
                    printer.print( model.getValueAt( rowIndex , columnIndex ) );
                }
                printer.println();
            }
        } catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

    private JTable newJTable ()
    {
        String[] columnNames = { "Species" , "Name" };
        Object[][] data = {
                { "Dog" , "Delilah" } ,
                { "Cat" , "René" } ,
                { "Bird" , "Jordan" }
        };
        JTable table = new JTable( data , columnNames );
        return table;
    }

    private void writeDummyFile ()
    {
        Path path = Paths.get( "/Users/basilbourque/dummy.txt" );
        // Use try-with-resources to auto-close the file if successfully opened.
        try ( BufferedWriter writer = Files.newBufferedWriter( path ) )
        {
            writer.write( "Bonjour le monde!" );
        } catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

}

【讨论】:

  • 我可以用一种方法完成所有这些吗?
  • @petelam 另外,请注意您的 CSVFormat(或等效格式,例如对 RFC 4180 的引用)必须与 CSV 文件一起传送。
  • @petelam 是的,您可以将所有这些都放在一种方法中。但你为什么想要?一般来说,你应该保持方法简短,专注于单一任务,重点狭窄。子任务可以移出到其他方法,所以一个方法调用其他方法。这使您的代码更易于阅读、更易于调试和更易于维护。查看main 方法,看看它读起来像论文大纲或书籍目录,这样您就可以了解正在发生的事情,而无需翻阅代码页。
【解决方案2】:

确保在关闭文件之前调用 csv.flush()。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 2013-08-22
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多