package io.ebeaninternal.server.text.csv;
// Original name: au.com.bytecode.opencsv.CSVReader
// rbygrave: Made some Java Generics tweaks to remove warnings
/**
* Copyright 2005 Bytecode Pty Ltd.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
Glen Smith's CSV reader released under Apache License version 2.
Author: Glen Smith
/**
* Glen Smith's CSV reader released under Apache License version 2.
*
* @author Glen Smith
*
*/
public class CsvUtilReader {
private final BufferedReader br;
private boolean hasNext = true;
private final char separator;
private final char quotechar;
private final int skipLines;
private boolean linesSkiped;
The default separator to use if none is supplied to the constructor. /** The default separator to use if none is supplied to the constructor. */
public static final char DEFAULT_SEPARATOR = ',';
The default quote character to use if none is supplied to the
constructor.
/**
* The default quote character to use if none is supplied to the
* constructor.
*/
public static final char DEFAULT_QUOTE_CHARACTER = '"';
The default line to start reading.
/**
* The default line to start reading.
*/
public static final int DEFAULT_SKIP_LINES = 0;
Constructs CSVReader using a comma for the separator.
Params: - reader –
the reader to an underlying CSV source.
/**
* Constructs CSVReader using a comma for the separator.
*
* @param reader
* the reader to an underlying CSV source.
*/
public CsvUtilReader(Reader reader) {
this(reader, DEFAULT_SEPARATOR);
}
Constructs CSVReader with supplied separator.
Params: - reader –
the reader to an underlying CSV source.
- separator –
the delimiter to use for separating entries.
/**
* Constructs CSVReader with supplied separator.
*
* @param reader
* the reader to an underlying CSV source.
* @param separator
* the delimiter to use for separating entries.
*/
public CsvUtilReader(Reader reader, char separator) {
this(reader, separator, DEFAULT_QUOTE_CHARACTER);
}
Constructs CSVReader with supplied separator and quote char.
Params: - reader –
the reader to an underlying CSV source.
- separator –
the delimiter to use for separating entries
- quotechar –
the character to use for quoted elements
/**
* Constructs CSVReader with supplied separator and quote char.
*
* @param reader
* the reader to an underlying CSV source.
* @param separator
* the delimiter to use for separating entries
* @param quotechar
* the character to use for quoted elements
*/
public CsvUtilReader(Reader reader, char separator, char quotechar) {
this(reader, separator, quotechar, DEFAULT_SKIP_LINES);
}
Constructs CSVReader with supplied separator and quote char.
Params: - reader –
the reader to an underlying CSV source.
- separator –
the delimiter to use for separating entries
- quotechar –
the character to use for quoted elements
- line –
the line number to skip for start reading
/**
* Constructs CSVReader with supplied separator and quote char.
*
* @param reader
* the reader to an underlying CSV source.
* @param separator
* the delimiter to use for separating entries
* @param quotechar
* the character to use for quoted elements
* @param line
* the line number to skip for start reading
*/
public CsvUtilReader(Reader reader, char separator, char quotechar, int line) {
this.br = new BufferedReader(reader);
this.separator = separator;
this.quotechar = quotechar;
this.skipLines = line;
}
Reads the entire file into a List with each element being a String[] of
tokens.
Throws: - IOException –
if bad things happen during the read
Returns: a List of String[], with each String[] representing a line of the
file.
/**
* Reads the entire file into a List with each element being a String[] of
* tokens.
*
* @return a List of String[], with each String[] representing a line of the
* file.
*
* @throws IOException
* if bad things happen during the read
*/
public List<String[]> readAll() throws IOException {
List<String[]> allElements = new ArrayList<>();
while (hasNext) {
String[] nextLineAsTokens = readNext();
if (nextLineAsTokens != null) {
allElements.add(nextLineAsTokens);
}
}
return allElements;
}
Reads the next line from the buffer and converts to a string array.
Throws: - IOException –
if bad things happen during the read
Returns: a string array with each comma-separated element as a separate
entry.
/**
* Reads the next line from the buffer and converts to a string array.
*
* @return a string array with each comma-separated element as a separate
* entry.
*
* @throws IOException
* if bad things happen during the read
*/
public String[] readNext() throws IOException {
String nextLine = getNextLine();
return hasNext ? parseLine(nextLine) : null;
}
Reads the next line from the file.
Throws: - IOException –
if bad things happen during the read
Returns: the next line from the file without trailing newline
/**
* Reads the next line from the file.
*
* @return the next line from the file without trailing newline
* @throws IOException
* if bad things happen during the read
*/
private String getNextLine() throws IOException {
if (!this.linesSkiped) {
for (int i = 0; i < skipLines; i++) {
br.readLine();
}
this.linesSkiped = true;
}
String nextLine = br.readLine();
if (nextLine == null) {
hasNext = false;
}
return hasNext ? nextLine : null;
}
Parses an incoming String and returns an array of elements.
Params: - nextLine –
the string to parse
Throws: - IOException – if bad things happen during the read
Returns: the comma-tokenized list of elements, or null if nextLine is null
/**
* Parses an incoming String and returns an array of elements.
*
* @param nextLine
* the string to parse
* @return the comma-tokenized list of elements, or null if nextLine is null
* @throws IOException if bad things happen during the read
*/
private String[] parseLine(String nextLine) throws IOException {
if (nextLine == null) {
return null;
}
List<String> tokensOnThisLine = new ArrayList<>();
StringBuilder sb = new StringBuilder();
boolean inQuotes = false;
do {
if (inQuotes) {
// continuing a quoted section, reappend newline
sb.append("\n");
nextLine = getNextLine();
if (nextLine == null)
break;
}
for (int i = 0; i < nextLine.length(); i++) {
char c = nextLine.charAt(i);
if (c == quotechar) {
// this gets complex... the quote may end a quoted block, or escape another quote.
// do a 1-char lookahead:
if (inQuotes // we are in quotes, therefore there can be escaped quotes in here.
&& nextLine.length() > (i + 1) // there is indeed another character to check.
&& nextLine.charAt(i + 1) == quotechar) { // ..and that char. is a quote also.
// we have two quote chars in a row == one quote char, so consume them both and
// put one on the token. we do *not* exit the quoted text.
sb.append(nextLine.charAt(i + 1));
i++;
} else {
inQuotes = !inQuotes;
// the tricky case of an embedded quote in the middle: a,bc"d"ef,g
if (i > 2 //not on the begining of the line
&& nextLine.charAt(i - 1) != this.separator //not at the begining of an escape sequence
&& nextLine.length() > (i + 1) &&
nextLine.charAt(i + 1) != this.separator //not at the end of an escape sequence
) {
sb.append(c);
}
}
} else if (c == separator && !inQuotes) {
tokensOnThisLine.add(sb.toString().trim());
sb = new StringBuilder(); // start work on next token
} else {
sb.append(c);
}
}
} while (inQuotes);
tokensOnThisLine.add(sb.toString().trim());
return tokensOnThisLine.toArray(new String[0]);
}
Closes the underlying reader.
Throws: - IOException – if the close fails
/**
* Closes the underlying reader.
*
* @throws IOException if the close fails
*/
public void close() throws IOException {
br.close();
}
}