Source for org.jfree.data.io.CSV

   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: }