/* =========================================================== * JFreeChart : a free chart library for the Java(tm) platform * =========================================================== * * (C) Copyright 2000-2011, by Object Refinery Limited and Contributors. * * Project Info: http://www.jfree.org/jfreechart/index.html * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * -------- * CSV.java * -------- * (C) Copyright 2003-2008, by Object Refinery Limited. * * Original Author: David Gilbert (for Object Refinery Limited); * Contributor(s): -; * * Changes * ------- * 24-Nov-2003 : Version 1 (DG); * */ package org.jfree.data.io; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.List; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; /** * A utility class for reading {@link CategoryDataset} data from a CSV file. * This initial version is very basic, and won't handle errors in the data * file very gracefully. */ public class CSV { /** The field delimiter. */ private char fieldDelimiter; /** The text delimiter. */ private char textDelimiter; /** * Creates a new CSV reader where the field delimiter is a comma, and the * text delimiter is a double-quote. */ public CSV() { this(',', '"'); } /** * Creates a new reader with the specified field and text delimiters. * * @param fieldDelimiter the field delimiter (usually a comma, semi-colon, * colon, tab or space). * @param textDelimiter the text delimiter (usually a single or double * quote). */ public CSV(char fieldDelimiter, char textDelimiter) { this.fieldDelimiter = fieldDelimiter; this.textDelimiter = textDelimiter; } /** * Reads a {@link CategoryDataset} from a CSV file or input source. * * @param in the input source. * * @return A category dataset. * * @throws IOException if there is an I/O problem. */ public CategoryDataset readCategoryDataset(Reader in) throws IOException { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); BufferedReader reader = new BufferedReader(in); List<String> columnKeys = null; int lineIndex = 0; String line = reader.readLine(); while (line != null) { if (lineIndex == 0) { // first line contains column keys columnKeys = extractColumnKeys(line); } else { // remaining lines contain a row key and data values extractRowKeyAndData(line, dataset, columnKeys); } line = reader.readLine(); lineIndex++; } return dataset; } /** * Extracts the column keys from a string. * * @param line a line from the input file. * * @return A list of column keys. */ private List<String> extractColumnKeys(String line) { List<String> keys = new java.util.ArrayList<String>(); int fieldIndex = 0; int start = 0; for (int i = 0; i < line.length(); i++) { if (line.charAt(i) == this.fieldDelimiter) { if (fieldIndex > 0) { // first field is ignored, since // column 0 is for row keys String key = line.substring(start, i); keys.add(removeStringDelimiters(key)); } start = i + 1; fieldIndex++; } } String key = line.substring(start, line.length()); keys.add(removeStringDelimiters(key)); return keys; } /** * Extracts the row key and data for a single line from the input source. * * @param line the line from the input source. * @param dataset the dataset to be populated. * @param columnKeys the column keys. */ private void extractRowKeyAndData(String line, DefaultCategoryDataset dataset, List<String> columnKeys) { Comparable rowKey = null; int fieldIndex = 0; int start = 0; for (int i = 0; i < line.length(); i++) { if (line.charAt(i) == this.fieldDelimiter) { if (fieldIndex == 0) { // first field contains the row key String key = line.substring(start, i); rowKey = removeStringDelimiters(key); } else { // remaining fields contain values Double value = Double.valueOf( removeStringDelimiters(line.substring(start, i)) ); dataset.addValue( value, rowKey, columnKeys.get(fieldIndex - 1) ); } start = i + 1; fieldIndex++; } } Double value = Double.valueOf( removeStringDelimiters(line.substring(start, line.length())) ); dataset.addValue( value, rowKey, columnKeys.get(fieldIndex - 1) ); } /** * Removes the string delimiters from a key (as well as any white space * outside the delimiters). * * @param key the key (including delimiters). * * @return The key without delimiters. */ private String removeStringDelimiters(String key) { String k = key.trim(); if (k.charAt(0) == this.textDelimiter) { k = k.substring(1); } if (k.charAt(k.length() - 1) == this.textDelimiter) { k = k.substring(0, k.length() - 1); } return k; } }