001: package prefuse.data.io;
002:
003: import java.io.BufferedReader;
004: import java.io.IOException;
005: import java.io.InputStream;
006: import java.io.InputStreamReader;
007:
008: import prefuse.data.parser.DataParseException;
009: import prefuse.data.parser.ParserFactory;
010:
011: /**
012: * TableReader for Comma Separated Value (CSV) files. CSV files list
013: * each row of a table on a line, separating each data column by a line.
014: * Typically the first line of the file is a header row indicating the
015: * names of each data column.
016: *
017: * For a more in-depth description of the CSV format, please see this
018: * <a href="http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm">
019: * CSV reference web page</a>.
020: *
021: * @author <a href="http://jheer.org">jeffrey heer</a>
022: */
023: public class CSVTableReader extends AbstractTextTableReader {
024:
025: /**
026: * Create a new CSVTableReader.
027: */
028: public CSVTableReader() {
029: super ();
030: }
031:
032: /**
033: * Create a new CSVTableReader.
034: * @param parserFactory the ParserFactory to use for parsing text strings
035: * into table values.
036: */
037: public CSVTableReader(ParserFactory parserFactory) {
038: super (parserFactory);
039: }
040:
041: /**
042: * @see prefuse.data.io.AbstractTextTableReader#read(java.io.InputStream, prefuse.data.io.TableReadListener)
043: */
044: public void read(InputStream is, TableReadListener trl)
045: throws IOException, DataParseException {
046: String line;
047: StringBuffer sbuf = new StringBuffer();
048:
049: boolean inRecord = false;
050: int inQuote = 0;
051: int lineno = 0;
052: int col = 0;
053:
054: BufferedReader br = new BufferedReader(
055: new InputStreamReader(is));
056: while ((line = br.readLine()) != null) {
057: // increment the line number
058: ++lineno;
059:
060: // extract the character array for quicker processing
061: char[] c = line.toCharArray();
062: int last = c.length - 1;
063:
064: // iterate through current line
065: for (int i = 0; i <= last; ++i) {
066: if (!inRecord) {
067: // not currently processing a record
068: if (Character.isWhitespace(c[i])) {
069: continue;
070: } else if (c[i] == '\"') {
071: inRecord = true;
072: inQuote = 1;
073: } else if (c[i] == ',') {
074: String s = sbuf.toString().trim();
075: trl.readValue(lineno, ++col, s);
076: sbuf.delete(0, sbuf.length());
077: } else {
078: inRecord = true;
079: sbuf.append(c[i]);
080: }
081: } else {
082: // in the midst of a record
083: if (inQuote == 1) {
084: if (c[i] == '\"'
085: && (i == last || c[i + 1] != '\"')) {
086: // end of quotation
087: inQuote = 2;
088: } else if (c[i] == '\"') {
089: // double quote so skip one ahead
090: sbuf.append(c[i++]);
091: } else {
092: sbuf.append(c[i]);
093: }
094: } else {
095: if (Character.isWhitespace(c[i])) {
096: sbuf.append(c[i]);
097: } else if (c[i] != ',' && inQuote == 2) {
098: throw new IllegalStateException(
099: "Invalid data format. "
100: + "Error at line " + lineno
101: + ", col " + i);
102: } else if (c[i] != ',') {
103: sbuf.append(c[i]);
104: } else {
105: String s = sbuf.toString().trim();
106: trl.readValue(lineno, ++col, s);
107: sbuf.delete(0, sbuf.length());
108: inQuote = 0;
109: inRecord = false;
110: }
111: }
112: }
113: }
114: if (inQuote != 1) {
115: String s = sbuf.toString().trim();
116: trl.readValue(lineno, ++col, s);
117: sbuf.delete(0, sbuf.length());
118: inQuote = 0;
119: inRecord = false;
120: }
121: if (!inRecord && col > 0) {
122: col = 0;
123: }
124: }
125: }
126:
127: } // end of class CSVTableReader
|