Skip to content

Commit

Permalink
Improved error message when buffer exceeds #52
Browse files Browse the repository at this point in the history
  • Loading branch information
osiegmar committed Feb 7, 2021
1 parent 090bfe1 commit 1a13691
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] - 2021-??-??
### Changed
- Small code improvement for writing field separators
- Improved error message when buffer exceeds (because of invalid CSV data) [\#52](https://github.com/osiegmar/FastCSV/issues/52)

## [2.0.0] - 2021-01-01
### Added
Expand Down
2 changes: 1 addition & 1 deletion config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
-->

<module name="LineLength">
<property name="max" value="100"/>
<property name="max" value="120"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>

Expand Down
7 changes: 6 additions & 1 deletion src/main/java/de/siegmar/fastcsv/reader/CsvReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,12 @@ private void fetch() {
try {
fetchedRow = fetchRow();
} catch (final IOException e) {
throw new UncheckedIOException(e);
if (fetchedRow != null) {
throw new UncheckedIOException("IOException when reading record that started in line "
+ (fetchedRow.getOriginalLineNumber() + 1), e);
} else {
throw new UncheckedIOException("IOException when reading first record", e);
}
}
fetched = true;
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/de/siegmar/fastcsv/reader/RowReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,9 @@ private static char[] extendAndRelocate(final char[] buf, final int begin)

final int newBufferSize = buf.length * 2;
if (newBufferSize > MAX_BUFFER_SIZE) {
throw new IOException("Maximum buffer size "
+ MAX_BUFFER_SIZE + " is not enough to read data");
throw new IOException("Maximum buffer size " + MAX_BUFFER_SIZE + " is not enough "
+ "to read data of a single field. Typically, this happens if quotation "
+ "started but did not end within this buffer's maximum boundary.");
}
final char[] newBuf = new char[newBufferSize];
System.arraycopy(buf, begin, newBuf, 0, buf.length - begin);
Expand Down
48 changes: 34 additions & 14 deletions src/test/java/blackbox/reader/CsvReaderTest.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package blackbox.reader;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.util.Arrays;
Expand Down Expand Up @@ -258,19 +256,41 @@ public void toStringWithoutHeader() {

@Test
public void bufferExceed() {
final byte[] buf = new byte[8 * 1024 * 1024];
Arrays.fill(buf, (byte) 'a');
buf[buf.length - 1] = (byte) ',';
final char[] buf = new char[8 * 1024 * 1024];
Arrays.fill(buf, 'X');
buf[buf.length - 1] = ',';

crb.build(new InputStreamReader(new ByteArrayInputStream(buf), UTF_8))
.iterator().next();
crb.build(new CharArrayReader(buf)).iterator().next();

buf[buf.length - 1] = (byte) 'a';
buf[buf.length - 1] = (byte) 'X';
final UncheckedIOException exception = assertThrows(UncheckedIOException.class, () ->
crb.build(new InputStreamReader(new ByteArrayInputStream(buf), UTF_8))
.iterator().next());
assertEquals("java.io.IOException: Maximum buffer size 8388608 is not enough to read data",
exception.getMessage());
crb.build(new CharArrayReader(buf)).iterator().next());
assertEquals("IOException when reading first record", exception.getMessage());

assertEquals("Maximum buffer size 8388608 is not enough to read data of a single field. "
+ "Typically, this happens if quotation started but did not end within this buffer's "
+ "maximum boundary.",
exception.getCause().getMessage());
}

@Test
public void bufferExceedSubsequentRecord() {
final char[] buf = new char[8 * 1024 * 1024];
Arrays.fill(buf, 'X');
final String s = "a,b,c\n\"";
System.arraycopy(s.toCharArray(), 0, buf, 0, s.length());

final CloseableIterator<CsvRow> iterator = crb.build(new CharArrayReader(buf)).iterator();

iterator.next();

final UncheckedIOException exception = assertThrows(UncheckedIOException.class, iterator::next);
assertEquals("IOException when reading record that started in line 2", exception.getMessage());

assertEquals("Maximum buffer size 8388608 is not enough to read data of a single field. "
+ "Typically, this happens if quotation started but did not end within this buffer's "
+ "maximum boundary.",
exception.getCause().getMessage());
}

// API
Expand Down Expand Up @@ -342,7 +362,7 @@ public void unreadable() {
final UncheckedIOException e = assertThrows(UncheckedIOException.class, () ->
crb.build(new UnreadableReader()).iterator().next());

assertEquals("java.io.IOException: Cannot read", e.getMessage());
assertEquals("IOException when reading first record", e.getMessage());
}

// test helpers
Expand Down

0 comments on commit 1a13691

Please sign in to comment.