package prefuse.data.io; import java.io.BufferedOutputStream; import java.io.OutputStream; import java.io.PrintStream; import prefuse.data.Table; import prefuse.util.TypeLib; import prefuse.util.collections.IntIterator; /** * TableWriter for fixed-width text files, that encode one row of table * data per line use a fixed number of characters for each data column. * Writing such tables requires use of a schema description that describes * the fixed-widths for each individual column. * The {@link prefuse.data.io.FixedWidthTextTableSchema} class provides * this functionality. A schema description must be written separately into * a different file. * * @author <a href="http://jheer.org">jeffrey heer</a> */ public class FixedWidthTextTableWriter extends AbstractTableWriter { // the schema description private FixedWidthTextTableSchema m_schema; /** * Creates a new FixedWidthTextTableWriter using the given schema. * @param schema the schema description of the fixed-width text column lengths */ public FixedWidthTextTableWriter(FixedWidthTextTableSchema schema) { m_schema = schema; } /** * Creates a new FixedWidthTextTableWriter using the schema at * the given location. * @param location a location string (filename, URL, or resource * locator) for the schema description of the fixed-width text column lengths * @throws DataIOException if an IO exception occurs while loading the schema */ public FixedWidthTextTableWriter(String location) throws DataIOException { this(FixedWidthTextTableSchema.load(location)); } // ------------------------------------------------------------------------ /** * Get the schema description describing the data columns' fixed widths * @return the fixed-width table schema description */ public FixedWidthTextTableSchema getFixedWidthSchema() { return m_schema; } /** * Set the schema description describing the data columns' fixed widths * @param schema the fixed-width table schema description */ public void setFixedWidthSchema(FixedWidthTextTableSchema schema) { m_schema = schema; } // ------------------------------------------------------------------------ /** * @see prefuse.data.io.TableWriter#writeTable(prefuse.data.Table, java.io.OutputStream) */ public void writeTable(Table table, OutputStream os) throws DataIOException { try { // get print stream PrintStream out = new PrintStream(new BufferedOutputStream(os)); // build array of column padding char[] pad = new char[table.getColumnCount()]; boolean[] pre = new boolean[table.getColumnCount()]; for (int i=0; i<table.getColumnCount(); ++i ) { Class type = table.getColumnType(i); pre[i] = TypeLib.isNumericType(type); pad[i] = pre[i] ? '0' : ' '; } // write out data for ( IntIterator rows = table.rows(); rows.hasNext(); ) { int row = rows.nextInt(); for ( int i=0; i<table.getColumnCount(); ++i ) { out.print(pack(table.getString(row, i), m_schema.getColumnLength(i), pre[i], pad[i])); } out.println(); } // finish up out.flush(); } catch ( Exception e ) { throw new DataIOException(e); } } /** * Pads or truncates a string as necessary to fit within the column length. */ private static String pack(String value, int len, boolean prepend, char pad) { int vlen = value.length(); if (vlen < len) { StringBuffer sbuf = new StringBuffer(); if (prepend) sbuf.append(value); for (int i=len; i<vlen; ++i) sbuf.append(pad); if (!prepend) sbuf.append(value); return sbuf.toString(); } else { return value.substring(0, len); } } } // end of class FixedWidthTextTableWriter