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:
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:
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:
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:
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(); } }