This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
commit 9121d65055362d073cc0f975cb7d35933d2d5e13 Author: Gary D. Gregory <garydgreg...@gmail.com> AuthorDate: Sun Apr 6 09:42:23 2025 -0400 [IO-639] ReversedLinesFileReader does not read first line if it's empty - Add `@Disabled` and parameterized version of "testEmptyFile" from PR #590 by elharo - Add 8192 buffer size test fixture - Parameterize ReversedLinesFileReaderSimpleTest for block size - Internal renaming from from PR #590 by elharo --- .../commons/io/input/ReversedLinesFileReader.java | 24 +++++++------- .../ReversedLinesFileReaderParamBlockSizeTest.java | 2 +- .../input/ReversedLinesFileReaderSimpleTest.java | 38 ++++++++++++++++------ .../org/apache/commons/io/empty-first-line.bin | 4 +++ 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java index 0ed22b264..79c34dd37 100644 --- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java +++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java @@ -126,7 +126,7 @@ public ReversedLinesFileReader get() throws IOException { } private final class FilePart { - private final long no; + private final long partNumber; private final byte[] data; @@ -137,19 +137,19 @@ private final class FilePart { /** * Constructs a new instance. * - * @param no the part number + * @param partNumber the part number * @param length its length * @param leftOverOfLastFilePart remainder * @throws IOException if there is a problem reading the file */ - private FilePart(final long no, final int length, final byte[] leftOverOfLastFilePart) throws IOException { - this.no = no; + private FilePart(final long partNumber, final int length, final byte[] leftOverOfLastFilePart) throws IOException { + this.partNumber = partNumber; final int dataLength = length + (leftOverOfLastFilePart != null ? leftOverOfLastFilePart.length : 0); this.data = new byte[dataLength]; - final long off = (no - 1) * blockSize; + final long off = (partNumber - 1) * blockSize; // read data - if (no > 0 /* file not empty */) { + if (partNumber > 0 /* file not empty */) { channel.position(off); final int countRead = channel.read(ByteBuffer.wrap(data, 0, length)); if (countRead != length) { @@ -209,7 +209,7 @@ private String readLine() { //NOPMD Bug in PMD String line = null; int newLineMatchByteCount; - final boolean isLastFilePart = no == 1; + final boolean isLastFilePart = partNumber == 1; int i = currentLastBytePos; while (i > -1) { @@ -249,7 +249,7 @@ private String readLine() { //NOPMD Bug in PMD // last file part handling if (isLastFilePart && leftOver != null) { - // there will be no line break anymore, this is the first line of the file + // there will be partNumber line break anymore, this is the first line of the file line = new String(leftOver, charset); leftOver = null; } @@ -270,8 +270,8 @@ private FilePart rollOver() throws IOException { + "last readLine() should have returned something! currentLastCharPos=" + currentLastBytePos); } - if (no > 1) { - return new FilePart(no - 1, blockSize, leftOver); + if (partNumber > 1) { + return new FilePart(partNumber - 1, blockSize, leftOver); } // NO 1 was the last FilePart, we're finished if (leftOver != null) { @@ -404,7 +404,7 @@ public ReversedLinesFileReader(final Path file, final int blockSize, final Chars final CharsetEncoder charsetEncoder = this.charset.newEncoder(); final float maxBytesPerChar = charsetEncoder.maxBytesPerChar(); if (maxBytesPerChar == 1f || this.charset == StandardCharsets.UTF_8) { - // all one byte encodings are no problem + // all one byte encodings are partNumber problem byteDecrement = 1; } else if (this.charset == Charset.forName("Shift_JIS") || // Same as for UTF-8 // http://www.herongyang.com/Unicode/JIS-Shift-JIS-Encoding.html @@ -523,7 +523,7 @@ public String readLine() throws IOException { while (line == null) { currentFilePart = currentFilePart.rollOver(); if (currentFilePart == null) { - // no more FileParts: we're done, leave line set to null + // partNumber more FileParts: we're done, leave line set to null break; } line = currentFilePart.readLine(); diff --git a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderParamBlockSizeTest.java b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderParamBlockSizeTest.java index 0926a925a..c03a6d01d 100644 --- a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderParamBlockSizeTest.java +++ b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderParamBlockSizeTest.java @@ -86,7 +86,7 @@ static void assertEqualsAndNoLineBreaks(final String expected, final String actu * Small and uneven block sizes are not used in reality but are good to show that the algorithm is solid. */ public static IntStream blockSizes() { - return IntStream.of(1, 3, 8, 256, 4096); + return IntStream.of(1, 3, 8, 10, 256, 4096, 8192); } private ReversedLinesFileReader reversedLinesFileReader; diff --git a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderSimpleTest.java b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderSimpleTest.java index a3e1db80d..b76ade8b2 100644 --- a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderSimpleTest.java +++ b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderSimpleTest.java @@ -30,13 +30,32 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.io.TestResources; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class ReversedLinesFileReaderSimpleTest { - @Test - public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException { - final int blockSize = 10; + /* + * Tests IO-639. + */ + @ParameterizedTest + @MethodSource("org.apache.commons.io.input.ReversedLinesFileReaderParamBlockSizeTest#blockSizes") + @Disabled + public void testEmptyFirstLine(final int blockSize) throws Exception { + final File testFileEmptyFirstLine = TestResources.getFile("/empty-first-line.bin"); + try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFileEmptyFirstLine, 10, StandardCharsets.US_ASCII.name())) { + assertEqualsAndNoLineBreaks("test2", reversedLinesFileReader.readLine()); + assertEqualsAndNoLineBreaks("", reversedLinesFileReader.readLine()); + assertEqualsAndNoLineBreaks("test1", reversedLinesFileReader.readLine()); + assertEqualsAndNoLineBreaks("", reversedLinesFileReader.readLine()); + } + } + + @ParameterizedTest + @MethodSource("org.apache.commons.io.input.ReversedLinesFileReaderParamBlockSizeTest#blockSizes") + public void testFileSizeIsExactMultipleOfBlockSize(final int blockSize) throws URISyntaxException, IOException { final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, StandardCharsets.ISO_8859_1.name())) { @@ -45,9 +64,9 @@ public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, } } - @Test - public void testLineCount() throws URISyntaxException, IOException { - final int blockSize = 10; + @ParameterizedTest + @MethodSource("org.apache.commons.io.input.ReversedLinesFileReaderParamBlockSizeTest#blockSizes") + public void testLineCount(final int blockSize) throws URISyntaxException, IOException { final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, StandardCharsets.ISO_8859_1.name())) { @@ -61,9 +80,9 @@ public void testLineCount() throws URISyntaxException, IOException { } } - @Test - public void testToString() throws URISyntaxException, IOException { - final int blockSize = 10; + @ParameterizedTest + @MethodSource("org.apache.commons.io.input.ReversedLinesFileReaderParamBlockSizeTest#blockSizes") + public void testToString(final int blockSize) throws URISyntaxException, IOException { final File testFile20Bytes = TestResources.getFile("/test-file-20byteslength.bin"); try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, StandardCharsets.ISO_8859_1.name())) { @@ -89,5 +108,4 @@ public void testUnsupportedEncodingUTF16() throws URISyntaxException { assertThrows(UnsupportedEncodingException.class, () -> new ReversedLinesFileReader(testFileEmpty, IOUtils.DEFAULT_BUFFER_SIZE, StandardCharsets.UTF_16.name()).close()); } - } diff --git a/src/test/resources/org/apache/commons/io/empty-first-line.bin b/src/test/resources/org/apache/commons/io/empty-first-line.bin new file mode 100644 index 000000000..4e0e6422d --- /dev/null +++ b/src/test/resources/org/apache/commons/io/empty-first-line.bin @@ -0,0 +1,4 @@ + +test1 + +test2