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
The following commit(s) were added to refs/heads/master by this push: new a6af211 Add ReversedLinesFileReader.readLines(int). a6af211 is described below commit a6af21186677821755f443fa69d9c46f8ff32029 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Tue Aug 11 21:04:20 2020 -0400 Add ReversedLinesFileReader.readLines(int). --- src/changes/changes.xml | 3 ++ .../commons/io/input/ReversedLinesFileReader.java | 34 +++++++++++++++++- .../input/ReversedLinesFileReaderTestSimple.java | 41 ++++++++++++---------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a5c034f..fda50bf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -92,6 +92,9 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="add" due-to="Gary Gregory"> Null-guard IOUtils.close(Closeable, IOConsumer). </action> + <action dev="ggregory" type="add" due-to="Gary Gregory"> + Add ReversedLinesFileReader.readLines(int). + </action> <action dev="ggregory" type="fix" due-to="Gary Gregory"> Replace FindBugs with SpotBugs. </action> 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 38f55e3..881c968 100644 --- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java +++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java @@ -28,6 +28,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.apache.commons.io.Charsets; import org.apache.commons.io.IOUtils; @@ -225,7 +228,7 @@ public class ReversedLinesFileReader implements Closeable { /** * Returns the lines of the file from bottom to top. - * + * * @return the next line or null if the start of the file is reached * @throws IOException if an I/O error occurs */ @@ -252,6 +255,35 @@ public class ReversedLinesFileReader implements Closeable { } /** + * Returns {@code lineCount} lines of the file from bottom to top. + * <p> + * If there are less than {@code lineCount} lines in the file, then that's what you get. + * </p> + * <p> + * Note: You can easily flip the result with {@link Collections#reverse(List)}. + * </p> + * + * @param lineCount How many lines to read. + * @return A new list + * @throws IOException if an I/O error occurs + * @since 2.8.0 + */ + public List<String> readLines(int lineCount) throws IOException { + if (lineCount < 0) { + throw new IllegalArgumentException("lineCount < 0"); + } + final ArrayList<String> arrayList = new ArrayList<>(lineCount); + for (int i = 0; i < lineCount; i++) { + final String line = readLine(); + if (line == null) { + return arrayList; + } + arrayList.add(line); + } + return arrayList; + } + + /** * Closes underlying resources. * * @throws IOException if an I/O error occurs diff --git a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.java b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.java index de6f3f0..3f4a7c9 100644 --- a/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.java +++ b/src/test/java/org/apache/commons/io/input/ReversedLinesFileReaderTestSimple.java @@ -18,53 +18,58 @@ package org.apache.commons.io.input; import static org.apache.commons.io.input.ReversedLinesFileReaderTestParamBlockSize.assertEqualsAndNoLineBreaks; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; +import java.util.List; import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; - public class ReversedLinesFileReaderTestSimple { - private ReversedLinesFileReader reversedLinesFileReader; - - @AfterEach - public void closeReader() { - try { - reversedLinesFileReader.close(); - } catch(final Exception e) { - // ignore + @Test + public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException { + final int blockSize = 10; + final File testFile20Bytes = new File(this.getClass().getResource("/test-file-20byteslength.bin").toURI()); + try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, + "ISO-8859-1")) { + assertEqualsAndNoLineBreaks("987654321", reversedLinesFileReader.readLine()); + assertEqualsAndNoLineBreaks("123456789", reversedLinesFileReader.readLine()); } } @Test - public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException { + public void testLineCount() throws URISyntaxException, IOException { final int blockSize = 10; final File testFile20Bytes = new File(this.getClass().getResource("/test-file-20byteslength.bin").toURI()); - reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, "ISO-8859-1"); - assertEqualsAndNoLineBreaks("987654321", reversedLinesFileReader.readLine()); - assertEqualsAndNoLineBreaks("123456789", reversedLinesFileReader.readLine()); + try (ReversedLinesFileReader reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, + "ISO-8859-1")) { + assertThrows(IllegalArgumentException.class, () -> reversedLinesFileReader.readLines(-1)); + assertTrue(reversedLinesFileReader.readLines(0).isEmpty()); + final List<String> lines = reversedLinesFileReader.readLines(2); + assertEqualsAndNoLineBreaks("987654321", lines.get(0)); + assertEqualsAndNoLineBreaks("123456789", lines.get(1)); + assertTrue(reversedLinesFileReader.readLines(0).isEmpty()); + assertTrue(reversedLinesFileReader.readLines(10000).isEmpty()); + } } @Test public void testUnsupportedEncodingUTF16() throws URISyntaxException { final File testFileEmpty = new File(this.getClass().getResource("/test-file-empty.bin").toURI()); assertThrows(UnsupportedEncodingException.class, - () -> new ReversedLinesFileReader(testFileEmpty, IOUtils.DEFAULT_BUFFER_SIZE, "UTF-16").close()); + () -> new ReversedLinesFileReader(testFileEmpty, IOUtils.DEFAULT_BUFFER_SIZE, "UTF-16").close()); } @Test public void testUnsupportedEncodingBig5() throws URISyntaxException { final File testFileEncodingBig5 = new File(this.getClass().getResource("/test-file-empty.bin").toURI()); assertThrows(UnsupportedEncodingException.class, - () -> new ReversedLinesFileReader(testFileEncodingBig5, IOUtils.DEFAULT_BUFFER_SIZE, "Big5").close()); + () -> new ReversedLinesFileReader(testFileEncodingBig5, IOUtils.DEFAULT_BUFFER_SIZE, "Big5").close()); } - - }