Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, 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-2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * Changes 36: * ------- 37: * 24-Nov-2003 : Version 1 (DG); 38: * 39: */ 40: 41: package org.jfree.data.io; 42: 43: import java.io.BufferedReader; 44: import java.io.IOException; 45: import java.io.Reader; 46: import java.util.List; 47: 48: import org.jfree.data.category.CategoryDataset; 49: import org.jfree.data.category.DefaultCategoryDataset; 50: 51: /** 52: * A utility class for reading {@link CategoryDataset} data from a CSV file. 53: * This initial version is very basic, and won't handle errors in the data 54: * file very gracefully. 55: */ 56: public class CSV { 57: 58: /** The field delimiter. */ 59: private char fieldDelimiter; 60: 61: /** The text delimiter. */ 62: private char textDelimiter; 63: 64: /** 65: * Creates a new CSV reader where the field delimiter is a comma, and the 66: * text delimiter is a double-quote. 67: */ 68: public CSV() { 69: this(',', '"'); 70: } 71: 72: /** 73: * Creates a new reader with the specified field and text delimiters. 74: * 75: * @param fieldDelimiter the field delimiter (usually a comma, semi-colon, 76: * colon, tab or space). 77: * @param textDelimiter the text delimiter (usually a single or double 78: * quote). 79: */ 80: public CSV(char fieldDelimiter, char textDelimiter) { 81: this.fieldDelimiter = fieldDelimiter; 82: this.textDelimiter = textDelimiter; 83: } 84: 85: /** 86: * Reads a {@link CategoryDataset} from a CSV file or input source. 87: * 88: * @param in the input source. 89: * 90: * @return A category dataset. 91: * 92: * @throws IOException if there is an I/O problem. 93: */ 94: public CategoryDataset readCategoryDataset(Reader in) throws IOException { 95: 96: DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 97: BufferedReader reader = new BufferedReader(in); 98: List columnKeys = null; 99: int lineIndex = 0; 100: String line = reader.readLine(); 101: while (line != null) { 102: if (lineIndex == 0) { // first line contains column keys 103: columnKeys = extractColumnKeys(line); 104: } 105: else { // remaining lines contain a row key and data values 106: extractRowKeyAndData(line, dataset, columnKeys); 107: } 108: line = reader.readLine(); 109: lineIndex++; 110: } 111: return dataset; 112: 113: } 114: 115: /** 116: * Extracts the column keys from a string. 117: * 118: * @param line a line from the input file. 119: * 120: * @return A list of column keys. 121: */ 122: private List extractColumnKeys(String line) { 123: List keys = new java.util.ArrayList(); 124: int fieldIndex = 0; 125: int start = 0; 126: for (int i = 0; i < line.length(); i++) { 127: if (line.charAt(i) == this.fieldDelimiter) { 128: if (fieldIndex > 0) { // first field is ignored, since 129: // column 0 is for row keys 130: String key = line.substring(start, i); 131: keys.add(removeStringDelimiters(key)); 132: } 133: start = i + 1; 134: fieldIndex++; 135: } 136: } 137: String key = line.substring(start, line.length()); 138: keys.add(removeStringDelimiters(key)); 139: return keys; 140: } 141: 142: /** 143: * Extracts the row key and data for a single line from the input source. 144: * 145: * @param line the line from the input source. 146: * @param dataset the dataset to be populated. 147: * @param columnKeys the column keys. 148: */ 149: private void extractRowKeyAndData(String line, 150: DefaultCategoryDataset dataset, 151: List columnKeys) { 152: Comparable rowKey = null; 153: int fieldIndex = 0; 154: int start = 0; 155: for (int i = 0; i < line.length(); i++) { 156: if (line.charAt(i) == this.fieldDelimiter) { 157: if (fieldIndex == 0) { // first field contains the row key 158: String key = line.substring(start, i); 159: rowKey = removeStringDelimiters(key); 160: } 161: else { // remaining fields contain values 162: Double value = Double.valueOf( 163: removeStringDelimiters(line.substring(start, i)) 164: ); 165: dataset.addValue( 166: value, rowKey, 167: (Comparable) columnKeys.get(fieldIndex - 1) 168: ); 169: } 170: start = i + 1; 171: fieldIndex++; 172: } 173: } 174: Double value = Double.valueOf( 175: removeStringDelimiters(line.substring(start, line.length())) 176: ); 177: dataset.addValue( 178: value, rowKey, (Comparable) columnKeys.get(fieldIndex - 1) 179: ); 180: } 181: 182: /** 183: * Removes the string delimiters from a key (as well as any white space 184: * outside the delimiters). 185: * 186: * @param key the key (including delimiters). 187: * 188: * @return The key without delimiters. 189: */ 190: private String removeStringDelimiters(String key) { 191: String k = key.trim(); 192: if (k.charAt(0) == this.textDelimiter) { 193: k = k.substring(1); 194: } 195: if (k.charAt(k.length() - 1) == this.textDelimiter) { 196: k = k.substring(0, k.length() - 1); 197: } 198: return k; 199: } 200: 201: }