All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.ac.starlink.table.formats.CsvTableWriter Maven / Gradle / Ivy

package uk.ac.starlink.table.formats;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import uk.ac.starlink.table.ColumnInfo;
import uk.ac.starlink.table.RowSequence;
import uk.ac.starlink.table.StarTable;
import uk.ac.starlink.table.StarTableWriter;
import uk.ac.starlink.table.Tables;
import uk.ac.starlink.util.ConfigMethod;

/**
 * A StarTableWriter which outputs to Comma-Separated Value format.
 * This format is readable by {@link CsvTableBuilder}.
 *
 * @author   Mark Taylor (Starlink)
 * @since    21 Sep 2004
 */
public class CsvTableWriter extends DocumentedStreamStarTableWriter {

    private boolean writeHeader_ = true;
    private int maxFieldChars_ = Integer.MAX_VALUE;

    /**
     * Constructs a default CSV table writer.
     * This doesn't write a header.
     */
    public CsvTableWriter() {
        this( true );
    }

    /**
     * Constructs a CSV table writer which optionally writes headers.
     *
     * @param  writeHeader  true iff you want the first output line to contain
     *         column names
     */
    public CsvTableWriter( boolean writeHeader ) {
        super( new String[] { "csv" } );
        setWriteHeader( writeHeader );
    }

    /**
     * Indicate whether an initial row containing column names should be
     * written.
     *
     * @param  writeHeader  true iff you want the first output line to contain
     *         column names
     */
    @ConfigMethod(
        property = "header",
        doc = "

If true, the first line of the CSV output will be " + "a header containing the column names; " + "if false, no header line is written and all lines " + "represent data rows.

", sequence = 1 ) public void setWriteHeader( boolean writeHeader ) { writeHeader_ = writeHeader; } /** * Indicates whether an initial row containing column names will be * written. * * @return whether the first output line will contain column names */ public boolean getWriteHeader() { return writeHeader_; } /** * Sets a limit on the number of characters that will be written * in a single field. Fields beyond this length will be truncated. * * @param maxFieldChars new limit */ @ConfigMethod( property = "maxCell", doc = "

Maximum width in characters of an output table cell. " + "Cells longer than this will be truncated.

", example = "160", sequence = 2 ) public void setMaxFieldChars( int maxFieldChars ) { maxFieldChars_ = maxFieldChars; } /** * Returns the limit on the number of characters that will be written * in a single field. Fields beyond this length will be truncated. * * @return current limit */ public int getMaxFieldChars() { return maxFieldChars_; } /** * Returns "CSV" or "CSV-noheader". */ public String getFormatName() { return writeHeader_ ? "CSV" : "CSV-noheader"; } public String getMimeType() { return "text/csv; header=\"" + ( writeHeader_ ? "present" : "absent" ) + "\""; } public boolean docIncludesExample() { return true; } public String getXmlDescription() { return readText( "CsvTableWriter.xml" ); } public void writeStarTable( StarTable table, OutputStream ostrm ) throws IOException { Writer out = new OutputStreamWriter( ostrm ); int ncol = table.getColumnCount(); ColumnInfo[] cinfos = Tables.getColumnInfos( table ); RowSequence rseq = table.getRowSequence(); try { /* Write the headings if required. */ if ( getWriteHeader() ) { String[] headRow = new String[ ncol ]; for ( int icol = 0; icol < ncol; icol++ ) { headRow[ icol ] = cinfos[ icol ].getName(); } writeRow( out, headRow ); } /* Write the data. */ String[] dataRow = new String[ ncol ]; while ( rseq.next() ) { Object[] row = rseq.getRow(); for ( int icol = 0; icol < ncol; icol++ ) { dataRow[ icol ] = cinfos[ icol ] .formatValue( row[ icol ], maxFieldChars_ ); } writeRow( out, dataRow ); } } finally { out.flush(); rseq.close(); } } /** * Writes an array of strings as one row of CSV output. * * @param out output stream * @param row array of strings, one for each cell in the row */ private void writeRow( Writer out, String[] row ) throws IOException { int ncol = row.length; for ( int icol = 0; icol < ncol; icol++ ) { writeField( out, row[ icol ] ); out.write( icol < ncol - 1 ? ',' : '\n' ); } } /** * Writes a single field of CSV output. Any special characters in * the value are escaped as necessary. * * @param out output stream * @param value field to write */ @SuppressWarnings("fallthrough") private void writeField( Writer out, String value ) throws IOException { /* Empty or null string, no output required. */ if ( value == null || value.length() == 0 ) { return; } else { /* Find out if we need to quote this string. */ int nchar = value.length(); boolean quoted = false; switch ( value.charAt( 0 ) ) { case ' ': case '\t': quoted = true; } switch ( value.charAt( nchar - 1 ) ) { case ' ': case '\t': quoted = true; } for ( int i = 0; i < nchar && ! quoted; i++ ) { switch ( value.charAt( i ) ) { case '\n': case '\r': case ',': case '"': quoted = true; } } /* If unquoted, it's very easy. */ if ( ! quoted ) { out.write( value ); } /* Otherwise we need to make a bit of effort. */ else { out.write( '"' ); for ( int i = 0; i < nchar; i++ ) { char c = value.charAt( i ); switch ( c ) { case '"': out.write( '"' ); default: out.write( c ); } } out.write( '"' ); } } } /** * Returns a selection of useful CsvTableWriters. * * @return array containing one writer with headers and one without */ public static StarTableWriter[] getStarTableWriters() { return new StarTableWriter[] { new CsvTableWriter( true ), new CsvTableWriter( false ), }; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy