001: /* ===========================================================
002: * JFreeChart : a free chart library for the Java(tm) platform
003: * ===========================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jfreechart/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * --------
028: * CSV.java
029: * --------
030: * (C) Copyright 2003, 2004, by Object Refinery Limited.
031: *
032: * Original Author: David Gilbert (for Object Refinery Limited);
033: * Contributor(s): -;
034: *
035: * $Id: CSV.java,v 1.3.2.1 2005/10/25 21:33:38 mungady Exp $
036: *
037: * Changes
038: * -------
039: * 24-Nov-2003 : Version 1 (DG);
040: *
041: */
042:
043: package org.jfree.data.io;
044:
045: import java.io.BufferedReader;
046: import java.io.IOException;
047: import java.io.Reader;
048: import java.util.List;
049:
050: import org.jfree.data.category.CategoryDataset;
051: import org.jfree.data.category.DefaultCategoryDataset;
052:
053: /**
054: * A utility class for reading {@link CategoryDataset} data from a CSV file.
055: * This initial version is very basic, and won't handle errors in the data
056: * file very gracefully.
057: */
058: public class CSV {
059:
060: /** The field delimiter. */
061: private char fieldDelimiter;
062:
063: /** The text delimiter. */
064: private char textDelimiter;
065:
066: /**
067: * Creates a new CSV reader where the field delimiter is a comma, and the
068: * text delimiter is a double-quote.
069: */
070: public CSV() {
071: this (',', '"');
072: }
073:
074: /**
075: * Creates a new reader with the specified field and text delimiters.
076: *
077: * @param fieldDelimiter the field delimiter (usually a comma, semi-colon,
078: * colon, tab or space).
079: * @param textDelimiter the text delimiter (usually a single or double
080: * quote).
081: */
082: public CSV(char fieldDelimiter, char textDelimiter) {
083: this .fieldDelimiter = fieldDelimiter;
084: this .textDelimiter = textDelimiter;
085: }
086:
087: /**
088: * Reads a {@link CategoryDataset} from a CSV file or input source.
089: *
090: * @param in the input source.
091: *
092: * @return A category dataset.
093: *
094: * @throws IOException if there is an I/O problem.
095: */
096: public CategoryDataset readCategoryDataset(Reader in)
097: throws IOException {
098:
099: DefaultCategoryDataset dataset = new DefaultCategoryDataset();
100: BufferedReader reader = new BufferedReader(in);
101: List columnKeys = null;
102: int lineIndex = 0;
103: String line = reader.readLine();
104: while (line != null) {
105: if (lineIndex == 0) { // first line contains column keys
106: columnKeys = extractColumnKeys(line);
107: } else { // remaining lines contain a row key and data values
108: extractRowKeyAndData(line, dataset, columnKeys);
109: }
110: line = reader.readLine();
111: lineIndex++;
112: }
113: return dataset;
114:
115: }
116:
117: /**
118: * Extracts the column keys from a string.
119: *
120: * @param line a line from the input file.
121: *
122: * @return A list of column keys.
123: */
124: private List extractColumnKeys(String line) {
125: List keys = new java.util.ArrayList();
126: int fieldIndex = 0;
127: int start = 0;
128: for (int i = 0; i < line.length(); i++) {
129: if (line.charAt(i) == this .fieldDelimiter) {
130: if (fieldIndex > 0) { // first field is ignored, since
131: // column 0 is for row keys
132: String key = line.substring(start, i);
133: keys.add(removeStringDelimiters(key));
134: }
135: start = i + 1;
136: fieldIndex++;
137: }
138: }
139: String key = line.substring(start, line.length());
140: keys.add(removeStringDelimiters(key));
141: return keys;
142: }
143:
144: /**
145: * Extracts the row key and data for a single line from the input source.
146: *
147: * @param line the line from the input source.
148: * @param dataset the dataset to be populated.
149: * @param columnKeys the column keys.
150: */
151: private void extractRowKeyAndData(String line,
152: DefaultCategoryDataset dataset, List columnKeys) {
153: Comparable rowKey = null;
154: int fieldIndex = 0;
155: int start = 0;
156: for (int i = 0; i < line.length(); i++) {
157: if (line.charAt(i) == this .fieldDelimiter) {
158: if (fieldIndex == 0) { // first field contains the row key
159: String key = line.substring(start, i);
160: rowKey = removeStringDelimiters(key);
161: } else { // remaining fields contain values
162: Double value = Double
163: .valueOf(removeStringDelimiters(line
164: .substring(start, i)));
165: dataset
166: .addValue(value, rowKey,
167: (Comparable) columnKeys
168: .get(fieldIndex - 1));
169: }
170: start = i + 1;
171: fieldIndex++;
172: }
173: }
174: Double value = Double.valueOf(removeStringDelimiters(line
175: .substring(start, line.length())));
176: dataset.addValue(value, rowKey, (Comparable) columnKeys
177: .get(fieldIndex - 1));
178: }
179:
180: /**
181: * Removes the string delimiters from a key (as well as any white space
182: * outside the delimiters).
183: *
184: * @param key the key (including delimiters).
185: *
186: * @return The key without delimiters.
187: */
188: private String removeStringDelimiters(String key) {
189: String k = key.trim();
190: if (k.charAt(0) == this .textDelimiter) {
191: k = k.substring(1);
192: }
193: if (k.charAt(k.length() - 1) == this .textDelimiter) {
194: k = k.substring(0, k.length() - 1);
195: }
196: return k;
197: }
198:
199: }
|