/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.io.*;
import java.util.*;
/** CSV in action: lines from a file and print. */
public class CSVFile {
public static void main(String[] args) throws IOException {
// Construct a new CSV parser.
CSV csv = new CSV();
if (args.length == 0) { // read standard input
BufferedReader is = new BufferedReader(
new InputStreamReader(System.in));
process(csv, is);
} else {
for (int i=0; i process(csv, new BufferedReader(new FileReader(args[i])));
}
}
}
protected static void process(CSV csv, BufferedReader is) throws IOException {
String line;
while ((line = is.readLine()) != null) {
System.out.println("line = `" + line + "'");
Iterator e = csv.parse(line).iterator();
int i = 0;
while (e.hasNext())
System.out.println("field[" + i++ + "] = `" +
e.next() + "'");
}
}
}
/** Parse comma-separated values (CSV), a common Windows file format.
* Sample input: "LU",86.25,"11/4/1998","2:19PM",+4.0625
*
* Inner logic adapted from a C++ original that was
* Copyright (C) 1999 Lucent Technologies
* Excerpted from 'The Practice of Programming'
* by Brian W. Kernighan and Rob Pike.
*
* Included by permission of the http://tpop.awl.com/ web site,
* which says:
* "You may use this code for any purpose, as long as you leave
* the copyright notice and book citation attached." I have done so.
* @author Brian W. Kernighan and Rob Pike (C++ original)
* @author Ian F. Darwin (translation into Java and removal of I/O)
* @author Ben Ballard (rewrote advQuoted to handle '""' and for readability)
*/
class CSV {
public static final char DEFAULT_SEP = ',';
/** Construct a CSV parser, with the default separator (`,'). */
public CSV() {
this(DEFAULT_SEP);
}
/** Construct a CSV parser with a given separator.
* @param sep The single char for the separator (not a list of
* separator characters)
*/
public CSV(char sep) {
fieldSep = sep;
}
/** The fields in the current String */
protected List list = new ArrayList();
/** the separator char for this parser */
protected char fieldSep;
/** parse: break the input String into fields
* @return java.util.Iterator containing each field
* from the original as a String, in order.
*/
public List parse(String line)
{
StringBuffer sb = new StringBuffer();
list.clear(); // recycle to initial state
int i = 0;
if (line.length() == 0) {
list.add(line);
return list;
}
do {
sb.setLength(0);
if (i < line.length() && line.charAt(i) == '"')
i = advQuoted(line, sb, ++i); // skip quote
else
i = advPlain(line, sb, i);
list.add(sb.toString());
i++;
} while (i < line.length());
return list;
}
/** advQuoted: quoted field; return index of next separator */
protected int advQuoted(String s, StringBuffer sb, int i)
{
int j;
int len= s.length();
for (j=i; j if (s.charAt(j) == '"' && j+1 < len) {
if (s.charAt(j+1) == '"') {
j++; // skip escape char
} else if (s.charAt(j+1) == fieldSep) { //next delimeter
j++; // skip end quotes
break;
}
} else if (s.charAt(j) == '"' && j+1 == len) { // end quotes at end of line
break; //done
}
sb.append(s.charAt(j)); // regular character.
}
return j;
}
/** advPlain: unquoted field; return index of next separator */
protected int advPlain(String s, StringBuffer sb, int i)
{
int j;
j = s.indexOf(fieldSep, i); // look for separator
if (j == -1) { // none found
sb.append(s.substring(i));
return s.length();
} else {
sb.append(s.substring(i, j));
return j;
}
}
}
//File:CSV.dat
/*
"Hello","World"
123,456
"LU",86.25|"11/4/1998"|"2:19PM"|+4.0625
bad "input",123e01
XYZZY,""|"OReilly & Associates| Inc."|"Darwin| Ian"|"a \"glug\" bit|"|5|"Memory fault| core NOT dumped"
*/