Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jfreechart/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * -------- 28: * CSV.java 29: * -------- 30: * (C) Copyright 2003, 2004, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: CSV.java,v 1.3.2.1 2005/10/25 21:33:38 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 24-Nov-2003 : Version 1 (DG); 40: * 41: */ 42: 43: package org.jfree.data.io; 44: 45: import java.io.BufferedReader; 46: import java.io.IOException; 47: import java.io.Reader; 48: import java.util.List; 49: 50: import org.jfree.data.category.CategoryDataset; 51: import org.jfree.data.category.DefaultCategoryDataset; 52: 53: /** 54: * A utility class for reading {@link CategoryDataset} data from a CSV file. 55: * This initial version is very basic, and won't handle errors in the data 56: * file very gracefully. 57: */ 58: public class CSV { 59: 60: /** The field delimiter. */ 61: private char fieldDelimiter; 62: 63: /** The text delimiter. */ 64: private char textDelimiter; 65: 66: /** 67: * Creates a new CSV reader where the field delimiter is a comma, and the 68: * text delimiter is a double-quote. 69: */ 70: public CSV() { 71: this(',', '"'); 72: } 73: 74: /** 75: * Creates a new reader with the specified field and text delimiters. 76: * 77: * @param fieldDelimiter the field delimiter (usually a comma, semi-colon, 78: * colon, tab or space). 79: * @param textDelimiter the text delimiter (usually a single or double 80: * quote). 81: */ 82: public CSV(char fieldDelimiter, char textDelimiter) { 83: this.fieldDelimiter = fieldDelimiter; 84: this.textDelimiter = textDelimiter; 85: } 86: 87: /** 88: * Reads a {@link CategoryDataset} from a CSV file or input source. 89: * 90: * @param in the input source. 91: * 92: * @return A category dataset. 93: * 94: * @throws IOException if there is an I/O problem. 95: */ 96: public CategoryDataset readCategoryDataset(Reader in) throws IOException { 97: 98: DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 99: BufferedReader reader = new BufferedReader(in); 100: List columnKeys = null; 101: int lineIndex = 0; 102: String line = reader.readLine(); 103: while (line != null) { 104: if (lineIndex == 0) { // first line contains column keys 105: columnKeys = extractColumnKeys(line); 106: } 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, 153: List columnKeys) { 154: Comparable rowKey = null; 155: int fieldIndex = 0; 156: int start = 0; 157: for (int i = 0; i < line.length(); i++) { 158: if (line.charAt(i) == this.fieldDelimiter) { 159: if (fieldIndex == 0) { // first field contains the row key 160: String key = line.substring(start, i); 161: rowKey = removeStringDelimiters(key); 162: } 163: else { // remaining fields contain values 164: Double value = Double.valueOf( 165: removeStringDelimiters(line.substring(start, i)) 166: ); 167: dataset.addValue( 168: value, rowKey, 169: (Comparable) columnKeys.get(fieldIndex - 1) 170: ); 171: } 172: start = i + 1; 173: fieldIndex++; 174: } 175: } 176: Double value = Double.valueOf( 177: removeStringDelimiters(line.substring(start, line.length())) 178: ); 179: dataset.addValue( 180: value, rowKey, (Comparable) columnKeys.get(fieldIndex - 1) 181: ); 182: } 183: 184: /** 185: * Removes the string delimiters from a key (as well as any white space 186: * outside the delimiters). 187: * 188: * @param key the key (including delimiters). 189: * 190: * @return The key without delimiters. 191: */ 192: private String removeStringDelimiters(String key) { 193: String k = key.trim(); 194: if (k.charAt(0) == this.textDelimiter) { 195: k = k.substring(1); 196: } 197: if (k.charAt(k.length() - 1) == this.textDelimiter) { 198: k = k.substring(0, k.length() - 1); 199: } 200: return k; 201: } 202: 203: }