Initial commit
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
"""Always forgive your enemies; nothing annoys them so much.""", Oscar Wilde
|
||||
"Zweite Zeile", völlig in, Ordnung
|
||||
"Escaped Chars\"", "in Quoted Fields \\", und \, außerhalb
|
||||
Spaces , und Tabs
|
||||
#Kommentarzeile, gefolgt von leerer Zeile
|
||||
|
||||
"#feld mit", "#Kommentarzeichen", #in den Feldern
|
||||
"field", "with
|
||||
CR inside"
|
||||
test1, te"st2, test3
|
||||
#"fehlerhafte", "Zeile
|
||||
#"gefolgt von", "korrekter Zeile"
|
||||
@@ -0,0 +1,11 @@
|
||||
"Buchungsdatum";"Valuta";"Betrag";"Waehrung";"Empfaengername1";"Empfaengername2";"Primanota";"BLZ Empfaenger";"Kontonummer Empfaenger";"Verwendungszweck 1";"Verwendungszweck 2"
|
||||
"27.07.05";"27.07.05";-29,00;"EUR";"KARTENSERVICE";"";"999010";"10050000";"5231240003";"VISA NR. 4555787019929887";"ABRECHNUNG VOM 22.07"
|
||||
"29.07.05";"29.07.05";-51,13;"EUR";"BHW BAUSPARKASSE HAMELN";"";"999010";"25410200";"471862300";"BHW 0471862 3 00 K CBA-05";""
|
||||
"01.08.05";"01.08.05";200,00;"EUR";"BAEUERLE-WALTHER,ERIKA";"";"999101";"10050000";"1320184258";"UNTERHALT";""
|
||||
"01.08.05";"01.08.05";115,00;"EUR";"WALTHER-STRATMANN,SIEGMUND";"";"853001";"10050000";"710150091";"UNTERHALT AUGUST 2005";""
|
||||
"01.08.05";"31.07.05";-20,00;"EUR";"";"";"954011";"10050000";"5310031253";"GA NR00001253 BLZ10050000 9";"31.07/09.23UHR FIL. 125"
|
||||
"02.08.05";"02.08.05";-13,20;"EUR";"CALL A PIZZA, BERLIN";"";"999011";"37010050";"555619501";"EC 68005963 30.07 19.56 ME9";""
|
||||
"02.08.05";"02.08.05";-25,32;"EUR";"VODAFONE D2";"";"999010";"30050000";"6444111";"000010753003 000265200517 0";"RECHNUNGSNR 103397270879"
|
||||
|
||||
"gebuchter Saldo";"02.08.05";1574,22;"EUR"
|
||||
"alter Saldo";"19.07.05";1397,87;"EUR"
|
||||
@@ -0,0 +1,3 @@
|
||||
Direktes Verarbeiten braucht Funktionalität eines Pull-Parsers:
|
||||
while ((row = parser.getNextRow()) != null) useRow;
|
||||
Weiterverarbeitung ins TableModel etc. wird von Wrappe-Klasse übernommen
|
||||
@@ -0,0 +1,150 @@
|
||||
package de.tilman.csvparser;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Repräsentiert eine CSV-Datei
|
||||
*
|
||||
* @author Tilman Walther
|
||||
*/
|
||||
public class CsvFile {
|
||||
|
||||
// TODO english comments
|
||||
|
||||
/* TODO andere Ausgabeformate.
|
||||
* http://www.ricebridge.com/products/csvman/api/com/ricebridge/csvman/CsvManager.html
|
||||
* The CsvManager class provides the following ways to load and save CSV data:
|
||||
* # As a List of String[] arrays - load(File), save(File,List)
|
||||
* # As a List of Lists of Strings - loadAsLists(File), saveAsLists(File,List)
|
||||
* # As a ResultSet - loadResultSet(File,boolean), save(File,ResultSet,boolean)
|
||||
* # As a TableModel - loadTableModel(File,boolean), save(File,TableModel,boolean)
|
||||
* # From callback interfaces - LineListener, FieldListener, LineProvider
|
||||
*/
|
||||
|
||||
CsvFileProperties properties;
|
||||
CsvParser parser;
|
||||
|
||||
File csvFile;
|
||||
int lineCounter = 0;
|
||||
|
||||
String[] header = null; // enthält die Tabellendefinition als Folge von Strings
|
||||
LinkedList data; // enthält die Zeilen der Tabelle als String-Arrays
|
||||
|
||||
/**
|
||||
* Der Konstruktor für den "default mode". Die CSV-Datei wird geöffnet und eingelesen, dabei
|
||||
* werden folgende Annahmen gemacht:
|
||||
* <ul>
|
||||
* <li>Jede Zeile enthält genau einen Datensatz</li>
|
||||
* <li>Trennzeichen zwischen Feldern ist , (Komma)</li>
|
||||
* <li>Das Zeichen für Einkapselung ist " (Doppelte Anführungsstriche)</li>
|
||||
* <li>Kommentarzeilen (mit #) sind nicht erlaubt</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param csvFile the CSV file
|
||||
* @throws IOException
|
||||
* @throws CsvParseException
|
||||
*/
|
||||
public CsvFile(File csvFile) throws IOException, CsvParseException {
|
||||
properties = new CsvFileProperties();
|
||||
//parser = new CsvLineParser(properties);
|
||||
this.csvFile = csvFile;
|
||||
readData();
|
||||
}
|
||||
|
||||
public CsvFile(File csvFile, CsvFileProperties properties) throws IOException, CsvParseException {
|
||||
this.properties = properties;
|
||||
//parser = new CsvLineParser(properties);
|
||||
this.csvFile = csvFile;
|
||||
readData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Daten aus der CSV-Datei zurück. Die LinkedList enthält die
|
||||
* Zeilen der Daten-Tabelle als String-Arrays.
|
||||
* @return the data of the csv file
|
||||
*/
|
||||
public LinkedList getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Spaltendefinition (d.h. die erste Zeile der Daten-Tabelle) zurück.
|
||||
* Falls die CSV-Datei laut CsvProperties keinen Header hat, wird null zurückgegeben.
|
||||
* @return the definition of the data table columns
|
||||
*/
|
||||
public String[] getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest die Daten aus der CSV-Datei
|
||||
* @throws CsvParseException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void readData() throws IOException, CsvParseException {
|
||||
|
||||
BufferedReader file;
|
||||
|
||||
try {
|
||||
file = new BufferedReader(new InputStreamReader(new FileInputStream(csvFile)));
|
||||
}
|
||||
catch (FileNotFoundException fnfe) {
|
||||
try {
|
||||
file = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(csvFile.getAbsolutePath())));
|
||||
}
|
||||
catch (NullPointerException npe) {
|
||||
throw new IOException("Die Datei '"+csvFile+"' konnte nicht geöffnet werden.");
|
||||
}
|
||||
}
|
||||
|
||||
CsvParser parser = new CsvParser(file, properties);
|
||||
|
||||
|
||||
String line;
|
||||
|
||||
try
|
||||
{
|
||||
// Spaltendefinition einlesen
|
||||
if (properties.headerInFirstLine()) {
|
||||
header = parser.getNextRow();
|
||||
if (header == null) {
|
||||
throw new IOException("Die Datei '"+csvFile+"' enthält keine Daten.");
|
||||
}
|
||||
}
|
||||
|
||||
data = new LinkedList();
|
||||
String[] row;
|
||||
|
||||
while (((row = parser.getNextRow()) != null) && (lineCounter < 50))
|
||||
{
|
||||
lineCounter++;
|
||||
data.add(row);
|
||||
}
|
||||
//System.out.println("Line counter at "+lineCounter);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw ioe;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package de.tilman.csvparser;
|
||||
|
||||
|
||||
/**
|
||||
* Properties of a CSV file.
|
||||
*
|
||||
* @author Tilman Walther
|
||||
*/
|
||||
public class CsvFileProperties {
|
||||
|
||||
// TODO Comments
|
||||
|
||||
public static final char DEFAULT_SEPARATOR = ',';
|
||||
public static final char DEFAULT_QUOTED_FIELD_MARKER = '"';
|
||||
public static final char DEFAULT_COMMENT_LINE_MARKER = '#';
|
||||
public static final char DEFAULT_ESCAPED_CHAR_MARKER = '\\';
|
||||
|
||||
/**
|
||||
* true, if the first line is the table header
|
||||
*/
|
||||
private boolean headerInFirstLine;
|
||||
|
||||
/**
|
||||
* the field separator character
|
||||
*/
|
||||
private char separator;
|
||||
|
||||
/**
|
||||
* true, if fields can be wrapped in quotes
|
||||
*/
|
||||
private boolean quotedFields;
|
||||
|
||||
/**
|
||||
* the character that wraps quoted fields
|
||||
*/
|
||||
private char quotedFieldMarker;
|
||||
|
||||
// private boolean doubleQuoteEscape;
|
||||
|
||||
private boolean commentLines;
|
||||
private char commentLineMarker;
|
||||
|
||||
private boolean escapedChars;
|
||||
private char escapedCharMarker;
|
||||
|
||||
private boolean ignoreEmptyLines;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for the default mode:
|
||||
* <ul>
|
||||
* <li>No header line</li>
|
||||
* <li>Separator = CsvFileProperties.DEFAULT_SEPARATOR</li>
|
||||
* <li>Quoted fields are allowed</li>
|
||||
* <li>Quoted field marker = CsvFileProperties.DEFAULT_QUOTED_FIELD_MARKER</li>
|
||||
* <li>Double quote escape allowed</li>
|
||||
* <li>No comment lines</li>
|
||||
* <li>No escaped characters</li>
|
||||
* <li>No empty lines</li>
|
||||
*/
|
||||
public CsvFileProperties() {
|
||||
headerInFirstLine = false;
|
||||
separator = DEFAULT_SEPARATOR;
|
||||
quotedFields = true;
|
||||
quotedFieldMarker = DEFAULT_QUOTED_FIELD_MARKER;
|
||||
// doubleQuoteEscape = true;
|
||||
commentLines = false;
|
||||
commentLineMarker = DEFAULT_COMMENT_LINE_MARKER;
|
||||
escapedChars = false;
|
||||
escapedCharMarker = DEFAULT_ESCAPED_CHAR_MARKER;
|
||||
ignoreEmptyLines = false;
|
||||
}
|
||||
|
||||
public CsvFileProperties(boolean headerInFirstLine, char separator,
|
||||
boolean quotedFields, char quotedFieldMarker,
|
||||
boolean doubleQuoteEscape, boolean commentLines,
|
||||
char commentLineMarker, boolean escapedChars,
|
||||
char escapedCharMarker, boolean ignoreEmptyLines) {
|
||||
this.headerInFirstLine = headerInFirstLine;
|
||||
this.separator = separator;
|
||||
this.quotedFields = quotedFields;
|
||||
this.quotedFieldMarker = quotedFieldMarker;
|
||||
// this.doubleQuoteEscape = doubleQuoteEscape;
|
||||
this.commentLines = commentLines;
|
||||
this.commentLineMarker = commentLineMarker;
|
||||
this.escapedChars = escapedChars;
|
||||
this.escapedCharMarker = escapedCharMarker;
|
||||
this.ignoreEmptyLines = ignoreEmptyLines;
|
||||
}
|
||||
|
||||
|
||||
public char getCommentLineMarker() {
|
||||
return commentLineMarker;
|
||||
}
|
||||
|
||||
public void setCommentLineMarker(char commentLineMarker) {
|
||||
this.commentLineMarker = commentLineMarker;
|
||||
}
|
||||
|
||||
public boolean commentLines() {
|
||||
return commentLines;
|
||||
}
|
||||
|
||||
public void setCommentLines(boolean commentLines) {
|
||||
this.commentLines = commentLines;
|
||||
}
|
||||
|
||||
// public boolean doubleQuoteEscape() {
|
||||
// return doubleQuoteEscape;
|
||||
// }
|
||||
//
|
||||
// public void setDoubleQuoteEscape(boolean doubleQuoteEscape) {
|
||||
// this.doubleQuoteEscape = doubleQuoteEscape;
|
||||
// }
|
||||
|
||||
public char getEscapedCharMarker() {
|
||||
return escapedCharMarker;
|
||||
}
|
||||
|
||||
public void setEscapedCharMarker(char escapedCharMarker) {
|
||||
this.escapedCharMarker = escapedCharMarker;
|
||||
}
|
||||
|
||||
public boolean escapedChars() {
|
||||
return escapedChars;
|
||||
}
|
||||
|
||||
public void setEscapedChars(boolean escapedChars) {
|
||||
this.escapedChars = escapedChars;
|
||||
}
|
||||
|
||||
public boolean headerInFirstLine() {
|
||||
return headerInFirstLine;
|
||||
}
|
||||
|
||||
public void setHeaderInFirstLine(boolean headerInFirstLine) {
|
||||
this.headerInFirstLine = headerInFirstLine;
|
||||
}
|
||||
|
||||
public boolean ignoreEmptyLines() {
|
||||
return ignoreEmptyLines;
|
||||
}
|
||||
|
||||
public void setIgnoreEmptyLines(boolean ignoreEmptyLines) {
|
||||
this.ignoreEmptyLines = ignoreEmptyLines;
|
||||
}
|
||||
|
||||
public char getQuotedFieldMarker() {
|
||||
return quotedFieldMarker;
|
||||
}
|
||||
|
||||
public void setQuotedFieldMarker(char quotedFieldMarker) {
|
||||
this.quotedFieldMarker = quotedFieldMarker;
|
||||
}
|
||||
|
||||
public boolean quotedFields() {
|
||||
return quotedFields;
|
||||
}
|
||||
|
||||
public void setQuotedFields(boolean quotedFields) {
|
||||
this.quotedFields = quotedFields;
|
||||
}
|
||||
|
||||
public char getSeparator() {
|
||||
return separator;
|
||||
}
|
||||
|
||||
public void setSeparator(char separator) {
|
||||
this.separator = separator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.tilman.csvparser;
|
||||
|
||||
|
||||
/**
|
||||
* @author Tilman Walther
|
||||
*/
|
||||
public class CsvParseException extends Exception {
|
||||
|
||||
int lineIndex = -1;
|
||||
|
||||
/**
|
||||
* This is the constructor used for the first step of the exception handling.
|
||||
* It stores the given column index. This index is used later while generating
|
||||
* the message string of the (final) exception.
|
||||
*
|
||||
* @param lineIndex the index of the line where the parse error occured
|
||||
*/
|
||||
public CsvParseException(int lineIndex) {
|
||||
this.lineIndex = lineIndex;
|
||||
}
|
||||
|
||||
public int getLineIndex() {
|
||||
return lineIndex;
|
||||
}
|
||||
|
||||
// /*
|
||||
// * This is the standard exception constructor.
|
||||
// *
|
||||
// * @param message
|
||||
// */
|
||||
// public CsvParseException(String message) {
|
||||
// super(message);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
package de.tilman.csvparser;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* @author Tilman Walther
|
||||
*/
|
||||
public class CsvParser {
|
||||
|
||||
/*
|
||||
* TODO Hält sich hoffentlich an alle Regeln
|
||||
* http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm#FileFormat
|
||||
* http://www.ricebridge.com/products/csvman/demo.htm
|
||||
*/
|
||||
|
||||
/**
|
||||
* the field separator character
|
||||
*/
|
||||
final char SEPARATOR;
|
||||
|
||||
/**
|
||||
* true, if fields can be wrapped in quotes, e.g. in order to use a carriage return
|
||||
* within fields. If false, the quote character is treated as a normal character.
|
||||
*/
|
||||
final boolean QUOTED_FIELDS;
|
||||
|
||||
/**
|
||||
* the quoting character
|
||||
*/
|
||||
final char QUOTED_FIELD_MARKER;
|
||||
|
||||
/**
|
||||
* true, if the CSV file can contain comment lines that shall be ignored by the parser
|
||||
*/
|
||||
final boolean COMMENTS;
|
||||
|
||||
/**
|
||||
* the comment character. If a line begins with this character and COMMENTS == true, the
|
||||
* line is ignored.
|
||||
*/
|
||||
final char COMMENT_LINE_MARKER;
|
||||
|
||||
/**
|
||||
* if true, all characters that follow the escaped char marker are inserted into the
|
||||
* field as they are
|
||||
*/
|
||||
final boolean ESCAPED_CHARS;
|
||||
|
||||
/**
|
||||
* the escape character
|
||||
*/
|
||||
final char ESCAPED_CHAR_MARKER;
|
||||
|
||||
/**
|
||||
* true, if ampty lines should be ignored by the parser. If false, empty lines are treated like
|
||||
* a line of empty fields.
|
||||
*/
|
||||
final boolean IGNORE_EMPTY_LINES;
|
||||
|
||||
|
||||
private final BufferedReader reader;
|
||||
|
||||
private final ArrayList row = new ArrayList(100);
|
||||
private final StringBuffer field = new StringBuffer(100);
|
||||
|
||||
public CsvParser(BufferedReader reader, CsvFileProperties properties) {
|
||||
SEPARATOR = properties.getSeparator();
|
||||
QUOTED_FIELDS = properties.quotedFields();
|
||||
QUOTED_FIELD_MARKER = properties.getQuotedFieldMarker();
|
||||
COMMENTS = properties.commentLines();
|
||||
COMMENT_LINE_MARKER = properties.getCommentLineMarker();
|
||||
ESCAPED_CHARS = properties.escapedChars();
|
||||
ESCAPED_CHAR_MARKER = properties.getEscapedCharMarker();
|
||||
IGNORE_EMPTY_LINES = properties.ignoreEmptyLines();
|
||||
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
// true, if the current character is the first of the row (and not inside a quoted field)
|
||||
private boolean newLine;
|
||||
|
||||
// true, if the pointer is behind a separator and the content of the field has not started
|
||||
private boolean newField;
|
||||
|
||||
// true, if the first character in the field was a quotation mark
|
||||
private boolean insideQuotedField;
|
||||
|
||||
// Number of successive spaces before the current character. (Spaces before a field's content aren't counted.)
|
||||
private final ArrayList spaces = new ArrayList(50);
|
||||
|
||||
// true, if the preceding row was finished by a carriage return '\r'
|
||||
private boolean terminatedByCR;
|
||||
|
||||
private int nextChar;
|
||||
|
||||
|
||||
protected void insertSpacesBefore() {
|
||||
// TODO ist spaces.size() performant?
|
||||
for (int i = 0; i < spaces.size(); i++) field.append(spaces.get(i));
|
||||
spaces.clear();
|
||||
}
|
||||
|
||||
protected String[] getRowAsStringArray() {
|
||||
// TODO was ist mit leeren Zeilen?
|
||||
row.add(field.toString());
|
||||
|
||||
// TODO Einsatzgebiet für Java 5 Generics und row.toArray()?
|
||||
final int rowLength = row.size();
|
||||
String[] resArray = new String[rowLength];
|
||||
for (int i = 0; i < rowLength; i++) {
|
||||
resArray[i] = (String) row.get(i);
|
||||
}
|
||||
|
||||
return resArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the next row of the table or null, if the end of the table is reached
|
||||
* @throws CsvParseException
|
||||
* @throws IOException
|
||||
*/
|
||||
public String[] getNextRow() throws CsvParseException, IOException {
|
||||
|
||||
newLine = true; // TODO wird newLine immer auf false gesetzt, wenn nötig? (Bis jetzt immer nach der IF-Behandlung in Zeile 210)
|
||||
newField = true;
|
||||
insideQuotedField = false;
|
||||
spaces.clear();
|
||||
terminatedByCR = false;
|
||||
|
||||
row.clear();
|
||||
field.setLength(0);
|
||||
|
||||
nextChar = reader.read();
|
||||
|
||||
while (nextChar != -1) {
|
||||
|
||||
// TODO was ist schneller: Globales ch (Allokation) oder final ch (Zugriff/Caching)?
|
||||
final char ch = (char) nextChar;
|
||||
|
||||
if (ch == SEPARATOR) {
|
||||
if (!insideQuotedField) {
|
||||
spaces.clear();
|
||||
newField = true;
|
||||
row.add(field.toString());
|
||||
field.setLength(0);
|
||||
}
|
||||
else {
|
||||
insertSpacesBefore();
|
||||
field.append(ch);
|
||||
}
|
||||
}
|
||||
else if ((ch == ' ') || (ch == '\t')) {
|
||||
if (!newField) {
|
||||
spaces.add(new Character(ch));
|
||||
}
|
||||
}
|
||||
else if (ch == QUOTED_FIELD_MARKER) {
|
||||
if (newField) {
|
||||
newField = false;
|
||||
insideQuotedField = true;
|
||||
}
|
||||
else if (insideQuotedField) {
|
||||
nextChar = reader.read();
|
||||
if (nextChar != -1) {
|
||||
// double qoute escape?
|
||||
char ch2 = (char) nextChar;
|
||||
if (ch2 == QUOTED_FIELD_MARKER) {
|
||||
insertSpacesBefore();
|
||||
field.append(QUOTED_FIELD_MARKER);
|
||||
}
|
||||
else {
|
||||
|
||||
// XXX Hier wird sehr viel gemacht. Sicherlich optimierbar.
|
||||
// Ab hier dürfen bis zum Ende des Feldes bzw. der Zeile nur
|
||||
// noch Spaces oder der Separator folgen
|
||||
|
||||
insideQuotedField = false;
|
||||
|
||||
while ((nextChar != -1) && (ch2 != SEPARATOR) && (ch2 != '\r') && (ch2 != '\n')) {
|
||||
nextChar = reader.read();
|
||||
ch2 = (char) nextChar;
|
||||
}
|
||||
|
||||
if (nextChar != -1) {
|
||||
if (ch2 == SEPARATOR) {
|
||||
spaces.clear();
|
||||
newField = true;
|
||||
row.add(field.toString());
|
||||
field.setLength(0);
|
||||
}
|
||||
else if (ch2 == '\r') {
|
||||
terminatedByCR = true;
|
||||
return getRowAsStringArray();
|
||||
}
|
||||
else if (ch2 == '\n') {
|
||||
return getRowAsStringArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
insertSpacesBefore();
|
||||
field.append(ch);
|
||||
}
|
||||
}
|
||||
else if (ch == '\r') {
|
||||
if (!insideQuotedField) {
|
||||
if ((!IGNORE_EMPTY_LINES) || (field.length() > 0)) {
|
||||
// terminatedByCR wird true gesetzt, damit ein direkt folgenden '\n' nicht erneut als
|
||||
// Zeilenumbruch interpretiert wird
|
||||
terminatedByCR = true;
|
||||
return getRowAsStringArray();
|
||||
}
|
||||
else {
|
||||
spaces.clear();
|
||||
newLine = true;
|
||||
newField = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
field.append(ch);
|
||||
}
|
||||
}
|
||||
else if (ch == '\n') {
|
||||
if (!insideQuotedField) {
|
||||
if ((!IGNORE_EMPTY_LINES) || (field.length() > 0)) {
|
||||
if (!terminatedByCR) {
|
||||
return getRowAsStringArray();
|
||||
}
|
||||
else {
|
||||
terminatedByCR = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
spaces.clear();
|
||||
newLine = true;
|
||||
newField = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
field.append(ch);
|
||||
}
|
||||
}
|
||||
else if (ESCAPED_CHARS && (ch == ESCAPED_CHAR_MARKER)) {
|
||||
newField = false;
|
||||
nextChar = reader.read();
|
||||
if (nextChar != -1) {
|
||||
insertSpacesBefore();
|
||||
field.append((char) nextChar);
|
||||
}
|
||||
else {
|
||||
// XXX der Parameter der CsvParseException muss korrekt sein
|
||||
throw new CsvParseException(0);
|
||||
}
|
||||
}
|
||||
else if (newLine && COMMENTS && (ch == COMMENT_LINE_MARKER)) {
|
||||
do {
|
||||
nextChar = reader.read();
|
||||
} while ((nextChar != '\n') && (nextChar != '\r'));
|
||||
if (nextChar == '\r') {
|
||||
terminatedByCR = true;
|
||||
}
|
||||
else {
|
||||
terminatedByCR = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
newField = false;
|
||||
insertSpacesBefore();
|
||||
field.append(ch);
|
||||
}
|
||||
|
||||
newLine = false;
|
||||
nextChar = reader.read();
|
||||
}
|
||||
|
||||
// TODO falls noch eine Zeile im Puffer ist, erst diese zurückgeben
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package de.tilman.csvparser.sample;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import de.tilman.csvparser.CsvFileProperties;
|
||||
import de.tilman.csvparser.CsvParser;
|
||||
|
||||
public class SampleUsage {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// TODO Pfad anpassen
|
||||
BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Eigene Dateien\\eclipse workspace\\CSVparser\\de\\tilman\\csvparser\\sample\\csvdata.txt")));
|
||||
|
||||
CsvParser parser = new CsvParser(file, new CsvFileProperties(false, ',', true, '"', true, true, '#', true, '\\', true));
|
||||
|
||||
String[] row;
|
||||
|
||||
while ((row = parser.getNextRow()) != null) {
|
||||
System.out.print(" | ");
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
System.out.print(row[i]);
|
||||
System.out.print(" | ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
// public static String row2string(String[] fields, boolean print) {
|
||||
// if (fields == null) return null;
|
||||
// StringBuffer buf = new StringBuffer();
|
||||
// for (int i = 0; i < (fields.length-1); i++) {
|
||||
// if (print) System.out.print(fields[i]+" | ");
|
||||
// buf.append(fields[i]+" | ");
|
||||
// }
|
||||
// if (print) System.out.println(fields[fields.length-1]);
|
||||
// buf.append(fields[fields.length-1]);
|
||||
// return buf.toString();
|
||||
// }
|
||||
//
|
||||
// public static void main(String[] args) throws Exception {
|
||||
// BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Eigene Dateien\\eclipse workspace\\CSVparser\\Testdaten.txt")));
|
||||
//
|
||||
// String[] resultStrings = {
|
||||
// "\"Always forgive your enemies; nothing annoys them so much.\" | Oscar Wilde",
|
||||
// "Zweite Zeile | völlig in | Ordnung",
|
||||
// "Escaped Chars\" | in Quoted Fields \\ | und , außerhalb",
|
||||
// "Spaces | und Tabs",
|
||||
// "",
|
||||
// "#feld mit | #Kommentarzeichen | #in den Feldern",
|
||||
// "field | with\nCR inside",
|
||||
// "test1 | te\"st2 | test3"
|
||||
// };
|
||||
//
|
||||
// CsvParser parser = new CsvParser(file, new CsvFileProperties(false, ',', true, '"', true, true, '#', true, '\\', false));
|
||||
// String result;
|
||||
// int errCount = 0;
|
||||
//
|
||||
// for (int i = 0; i < resultStrings.length; i++) {
|
||||
// System.out.println("\nIndex "+i);
|
||||
// result = row2string(parser.getNextRow(), true);
|
||||
// System.out.println(resultStrings[i]+" (check)");
|
||||
// if (result == null) {
|
||||
// if (resultStrings[i] == null) {
|
||||
// System.out.println(" --> erfolgreich");
|
||||
// }
|
||||
// else {
|
||||
// errCount++;
|
||||
// System.out.println(" --> FEHLER!");
|
||||
// }
|
||||
// }
|
||||
// else if (result.equals(resultStrings[i])) {
|
||||
// System.out.println(" --> erfolgreich");
|
||||
// }
|
||||
// else {
|
||||
// errCount++;
|
||||
// System.out.println(" --> FEHLER!");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (errCount == 0) {
|
||||
// System.out.println("\n\nAlle Tests erfolgreich durchgeführt.");
|
||||
// }
|
||||
// else {
|
||||
// System.err.println("\n\n"+errCount+" Fehler aufgetreten");
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# a CSV file with comment lines, empty lines and double quote escaping
|
||||
|
||||
"This", "is", "the", "first", "line"
|
||||
|
||||
This, is, the, second, line
|
||||
|
||||
"""I often quote myself. It adds spice to my conversation.""", "George Bernard Shaw", "(1850 - 1896)"
|
||||
|
||||
"This is a", "line with
|
||||
CR", "inside a field"
|
||||
Reference in New Issue
Block a user