* spaces need quotes), add the character, then continue to next character.
*/
isEscape = false;
if( this.strictQuotes && espectQuote ) {
throw new SuperCsvException(
String.format(
"strictQuotes: quotes needed at line %d column %d. To proceed, " +
"either quote the column or remove --strictquotes",
getLineNumber(), columns.size() + 1));
}
if( !surroundingSpacesNeedQuotes || currentColumn.length() > 0 ) {
appendSpaces(currentColumn, potentialSpaces);
}
potentialSpaces = 0;
currentColumn.append(c);
}
else if( c == escapeChar && !(line.charAt(charIndex+1) == 'N') ) {
isEscape = true;
}
else if( c == delimeterChar ) {
/*
* Delimiter. Save the column (trim trailing space if required) then continue to next character.
*/
espectQuote = true;
if( !surroundingSpacesNeedQuotes ) {
appendSpaces(currentColumn, potentialSpaces);
}
columns.add(currentColumn.length() > 0 ? currentColumn.toString() : null); // "" -> null
potentialSpaces = 0;
currentColumn.setLength(0);
} else if( c == SPACE ) {
/*
* Space. Remember it, then continue to next character.
*/
potentialSpaces++;
} else if( c == NEWLINE ) {
/*
* Newline. Add any required spaces (if surrounding spaces don't need quotes) and return (we've read
* a line!).
*/
if( !surroundingSpacesNeedQuotes ) {
appendSpaces(currentColumn, potentialSpaces);
}
columns.add(currentColumn.length() > 0 ? currentColumn.toString() : null); // "" -> null
return true;
} else if( c == quoteChar ) {
/*
* A single quote ("). Update to QUOTESCOPE (but don't save quote), then continue to next character.
*/
espectQuote = false;
state = TokenizerState.QUOTE_MODE;
quoteScopeStartingLine = getLineNumber();
// cater for spaces before a quoted section (be lenient!)
if( !surroundingSpacesNeedQuotes || currentColumn.length() > 0 ) {
appendSpaces(currentColumn, potentialSpaces);
}
potentialSpaces = 0;
} else {
/*
* Just a normal character. Add any required spaces (but trim any leading spaces if surrounding
* spaces need quotes), add the character, then continue to next character.
*/
if( this.strictQuotes && espectQuote ) {
throw new SuperCsvException(
String.format(
"strictQuotes: quotes needed at line %d column %d. To proceed, " +
"either quote the column or remove --strictquotes",
getLineNumber(), columns.size() + 1));
}
if( !surroundingSpacesNeedQuotes || currentColumn.length() > 0 ) {
appendSpaces(currentColumn, potentialSpaces);
}
potentialSpaces = 0;
currentColumn.append(c);
}
} else {
/*
* QUOTE_MODE (within quotes).
*/
if( sawNewLineInQuote ) {
if( currentColumn.length() > columnSizeLimit ) {
state = TokenizerState.NORMAL;
sawNewLineInQuote = false;
throw new SuperCsvException(
String
.format(
"oversized column while reading quoted column %d beginning on line %d and ending on line %d. " +
"See --columnsizelimit.",
columns.size() + 1, quoteScopeStartingLine, getLineNumber()));
}
}
if( c == NEWLINE ) {
/*
* Newline. Doesn't count as newline while in QUOTESCOPE. Add the newline char, reset the charIndex
* (will update to 0 for next iteration), read in the next line, then then continue to next
* character. For a large file with an unterminated quoted section (no trailing quote), this could
* cause memory issues as it will keep reading lines looking for the trailing quote. Maybe there
* should be a configurable limit on max lines to read in quoted mode?
*
* Yes I'll set the limit to be 16*1024*1024B = 16MB by default
*/
if( currentColumn.length() > columnSizeLimit ) {
state = TokenizerState.NORMAL;
sawNewLineInQuote = false;
throw new SuperCsvException(
String
.format(
"oversized column while reading quoted column %d beginning on line %d and ending on line %d. " +
"See --columnsizelimit.",
columns.size() + 1, quoteScopeStartingLine, getLineNumber()));
}
sawNewLineInQuote = true;
currentColumn.append(NEWLINE);
currentRow.append(NEWLINE); // specific line terminator lost, \n will have to suffice
charIndex = -1;
line = readLine();
if( line == null ) {
throw new SuperCsvException(
String
.format(
"unexpected end of file while reading quoted column %d beginning on line %d and ending on line %d",
columns.size() + 1, quoteScopeStartingLine, getLineNumber()));
}