-1

I am trying to export content of a JTable to a .csv file. I tried some code, there is no error but the file I intended to write does not get written. Could anyone see why? Thanks

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;
}
petelam
  • 43
  • 7
  • Search Stack Overflow before posting. Writing to files, and writing CSV, has been covered many times, with fully working code examples for you to follow. Tip: Use a library such as Apache Commons CSV. – Basil Bourque Jun 19 '19 at 21:22
  • Do you receive any error messages? It also looks like you're writing to `/tmp`, from my understanding there is no guarantee that files in `/tmp` will stick around for long. – hooknc Jun 19 '19 at 21:29
  • If you can, you should always use an external library for creating csv files (because you would need to escape certain characters). However, it seems that in this case you are having trouble writing to the file, which is not csv related – EDToaster Jun 19 '19 at 21:43

2 Answers2

1

Practice with a simple file

Take baby steps. First, be sure you are opening a file successfully.

Modern Java offers the Path, File, and Files classes to make handling files on storage much easier.

Example:

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() ;
        }
    }

}

Use a library for CSV

Next, for CSV or Tab-delimited files or such, use a library. I use Apache Commons CSV. Search Stack Overflow for many examples of using this and other such libraries to read and write these kinds of files.

Use CSVFormat to define the type of file. Here we use standard CSV as defined by RFC 4180. Note that standard CSV uses CRLF (CARRIAGE RETURN LINE FEED) to denote line breaks rather then LF (LINE FEED) seen commonly in Unix-like platforms.

When opening the file, we specify UTF-8 character encoding. UTF-8 is generally the best encoding to use; it covers all the Unicode characters, and is a superset of US-ASCII.

The CSVPrinter::print method adds a field at a time when outputting a row. We terminate the row by calling CSVPrinter::println.

I renamed your i & j variables to be meaningful.

I added column names at the top of the file. You may want to keep or discard that feature, up to you.

Notice how we are using try-with-resources syntax to auto-close our file.

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();
        }
    }

}
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • could I do all that in one method? – petelam Jun 20 '19 at 12:50
  • @petelam Also, note that your CSVFormat (or equivalent, such as a reference to RFC 4180) must be communicated along with the CSV file. – Tom Blodget Jun 20 '19 at 15:28
  • @petelam Yes, you could put all that into one method. But why would you want to? Generally, you should keep a method short, focused on a single task with a narrow focus. Sub-tasks can be moved out to other methods, so one method calls other methods. This makes your code easier to read, easier to debug, and easier to maintain. Look at the `main` method, see how it reads like an outline for a paper or a table-of-contents of a book, so you can get a sense of what's going on without wading through pages of code. – Basil Bourque Jun 20 '19 at 20:11
0

Make sure you call csv.flush() before closing the file. :)

Navid Mitchell
  • 1,276
  • 11
  • 10