You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/08/18 19:17:27 UTC
[commons-io] branch master updated: Sort methods in AB order.
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 9a212e8 Sort methods in AB order.
9a212e8 is described below
commit 9a212e86adc1828f8ff998956a14699fe337a38f
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Aug 18 15:17:17 2020 -0400
Sort methods in AB order.
---
.../commons/io/input/ReversedLinesFileReader.java | 392 ++++++++++-----------
1 file changed, 196 insertions(+), 196 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 d5f3fdd..872222e 100644
--- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
+++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
@@ -43,19 +43,178 @@ import org.apache.commons.io.IOUtils;
*/
public class ReversedLinesFileReader implements Closeable {
+ private class FilePart {
+ private final long no;
+
+ private final byte[] data;
+
+ private byte[] leftOver;
+
+ private int currentLastBytePos;
+
+ /**
+ * ctor
+ * @param no 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;
+ final int dataLength = length + (leftOverOfLastFilePart != null ? leftOverOfLastFilePart.length : 0);
+ this.data = new byte[dataLength];
+ final long off = (no - 1) * blockSize;
+
+ // read data
+ if (no > 0 /* file not empty */) {
+ channel.position(off);
+ final int countRead = channel.read(ByteBuffer.wrap(data, 0, length));
+ if (countRead != length) {
+ throw new IllegalStateException("Count of requested bytes and actually read bytes don't match");
+ }
+ }
+ // copy left over part into data arr
+ if (leftOverOfLastFilePart != null) {
+ System.arraycopy(leftOverOfLastFilePart, 0, data, length, leftOverOfLastFilePart.length);
+ }
+ this.currentLastBytePos = data.length - 1;
+ this.leftOver = null;
+ }
+
+ /**
+ * Creates the buffer containing any left over bytes.
+ */
+ private void createLeftOver() {
+ final int lineLengthBytes = currentLastBytePos + 1;
+ if (lineLengthBytes > 0) {
+ // create left over for next block
+ leftOver = new byte[lineLengthBytes];
+ System.arraycopy(data, 0, leftOver, 0, lineLengthBytes);
+ } else {
+ leftOver = null;
+ }
+ currentLastBytePos = -1;
+ }
+
+ /**
+ * Finds the new-line sequence and return its length.
+ *
+ * @param data buffer to scan
+ * @param i start offset in buffer
+ * @return length of newline sequence or 0 if none found
+ */
+ private int getNewLineMatchByteCount(final byte[] data, final int i) {
+ for (final byte[] newLineSequence : newLineSequences) {
+ boolean match = true;
+ for (int j = newLineSequence.length - 1; j >= 0; j--) {
+ final int k = i + j - (newLineSequence.length - 1);
+ match &= k >= 0 && data[k] == newLineSequence[j];
+ }
+ if (match) {
+ return newLineSequence.length;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Reads a line.
+ *
+ * @return the line or null
+ * @throws IOException if there is an error reading from the file
+ */
+ private String readLine() throws IOException {
+
+ String line = null;
+ int newLineMatchByteCount;
+
+ final boolean isLastFilePart = no == 1;
+
+ int i = currentLastBytePos;
+ while (i > -1) {
+
+ if (!isLastFilePart && i < avoidNewlineSplitBufferSize) {
+ // avoidNewlineSplitBuffer: for all except the last file part we
+ // take a few bytes to the next file part to avoid splitting of newlines
+ createLeftOver();
+ break; // skip last few bytes and leave it to the next file part
+ }
+
+ // --- check for newline ---
+ if ((newLineMatchByteCount = getNewLineMatchByteCount(data, i)) > 0 /* found newline */) {
+ final int lineStart = i + 1;
+ final int lineLengthBytes = currentLastBytePos - lineStart + 1;
+
+ if (lineLengthBytes < 0) {
+ throw new IllegalStateException("Unexpected negative line length="+lineLengthBytes);
+ }
+ final byte[] lineData = new byte[lineLengthBytes];
+ System.arraycopy(data, lineStart, lineData, 0, lineLengthBytes);
+
+ line = new String(lineData, encoding);
+
+ currentLastBytePos = i - newLineMatchByteCount;
+ break; // found line
+ }
+
+ // --- move cursor ---
+ i -= byteDecrement;
+
+ // --- end of file part handling ---
+ if (i < 0) {
+ createLeftOver();
+ break; // end of file part
+ }
+ }
+
+ // --- last file part handling ---
+ if (isLastFilePart && leftOver != null) {
+ // there will be no line break anymore, this is the first line of the file
+ line = new String(leftOver, encoding);
+ leftOver = null;
+ }
+
+ return line;
+ }
+
+ /**
+ * Handles block rollover
+ *
+ * @return the new FilePart or null
+ * @throws IOException if there was a problem reading the file
+ */
+ private FilePart rollOver() throws IOException {
+
+ if (currentLastBytePos > -1) {
+ throw new IllegalStateException("Current currentLastCharPos unexpectedly positive... "
+ + "last readLine() should have returned something! currentLastCharPos=" + currentLastBytePos);
+ }
+
+ if (no > 1) {
+ return new FilePart(no - 1, blockSize, leftOver);
+ }
+ // NO 1 was the last FilePart, we're finished
+ if (leftOver != null) {
+ throw new IllegalStateException("Unexpected leftover of the last block: leftOverOfThisFilePart="
+ + new String(leftOver, encoding));
+ }
+ return null;
+ }
+ }
private static final String EMPTY_STRING = "";
- private static final int DEFAULT_BLOCK_SIZE = IOUtils.DEFAULT_BUFFER_SIZE;
+ private static final int DEFAULT_BLOCK_SIZE = IOUtils.DEFAULT_BUFFER_SIZE;
private final int blockSize;
+
private final Charset encoding;
private final SeekableByteChannel channel;
-
private final long totalByteLength;
- private final long totalBlockCount;
+ private final long totalBlockCount;
private final byte[][] newLineSequences;
private final int avoidNewlineSplitBufferSize;
+
private final int byteDecrement;
private FilePart currentFilePart;
@@ -91,17 +250,20 @@ public class ReversedLinesFileReader implements Closeable {
}
/**
- * Creates a ReversedLinesFileReader with default block size of 4KB and the
- * specified encoding.
+ * Creates a ReversedLinesFileReader with the given block size and encoding.
*
* @param file
* the file to be read
- * @param charset the charset to use
+ * @param blockSize
+ * size of the internal buffer (for ideal performance this should
+ * match with the block size of the underlying file system).
+ * @param encoding
+ * the encoding of the file
* @throws IOException if an I/O error occurs
- * @since 2.7
+ * @since 2.3
*/
- public ReversedLinesFileReader(final Path file, final Charset charset) throws IOException {
- this(file, DEFAULT_BLOCK_SIZE, charset);
+ public ReversedLinesFileReader(final File file, final int blockSize, final Charset encoding) throws IOException {
+ this(file.toPath(), blockSize, encoding);
}
/**
@@ -115,13 +277,28 @@ public class ReversedLinesFileReader implements Closeable {
* @param encoding
* the encoding of the file
* @throws IOException if an I/O error occurs
- * @since 2.3
+ * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in
+ * version 2.2 if the encoding is not supported.
*/
- public ReversedLinesFileReader(final File file, final int blockSize, final Charset encoding) throws IOException {
+ public ReversedLinesFileReader(final File file, final int blockSize, final String encoding) throws IOException {
this(file.toPath(), blockSize, encoding);
}
/**
+ * Creates a ReversedLinesFileReader with default block size of 4KB and the
+ * specified encoding.
+ *
+ * @param file
+ * the file to be read
+ * @param charset the charset to use
+ * @throws IOException if an I/O error occurs
+ * @since 2.7
+ */
+ public ReversedLinesFileReader(final Path file, final Charset charset) throws IOException {
+ this(file, DEFAULT_BLOCK_SIZE, charset);
+ }
+
+ /**
* Creates a ReversedLinesFileReader with the given block size and encoding.
*
* @param file
@@ -197,33 +374,25 @@ public class ReversedLinesFileReader implements Closeable {
* @param blockSize
* size of the internal buffer (for ideal performance this should
* match with the block size of the underlying file system).
- * @param encoding
+ * @param charsetName
* the encoding of the file
* @throws IOException if an I/O error occurs
* @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in
* version 2.2 if the encoding is not supported.
+ * @since 2.7
*/
- public ReversedLinesFileReader(final File file, final int blockSize, final String encoding) throws IOException {
- this(file.toPath(), blockSize, encoding);
+ public ReversedLinesFileReader(final Path file, final int blockSize, final String charsetName) throws IOException {
+ this(file, blockSize, Charsets.toCharset(charsetName));
}
/**
- * Creates a ReversedLinesFileReader with the given block size and encoding.
+ * Closes underlying resources.
*
- * @param file
- * the file to be read
- * @param blockSize
- * size of the internal buffer (for ideal performance this should
- * match with the block size of the underlying file system).
- * @param charsetName
- * the encoding of the file
* @throws IOException if an I/O error occurs
- * @throws java.nio.charset.UnsupportedCharsetException thrown instead of {@link UnsupportedEncodingException} in
- * version 2.2 if the encoding is not supported.
- * @since 2.7
*/
- public ReversedLinesFileReader(final Path file, final int blockSize, final String charsetName) throws IOException {
- this(file, blockSize, Charsets.toCharset(charsetName));
+ @Override
+ public void close() throws IOException {
+ channel.close();
}
/**
@@ -283,173 +452,4 @@ public class ReversedLinesFileReader implements Closeable {
return arrayList;
}
- /**
- * Closes underlying resources.
- *
- * @throws IOException if an I/O error occurs
- */
- @Override
- public void close() throws IOException {
- channel.close();
- }
-
- private class FilePart {
- private final long no;
-
- private final byte[] data;
-
- private byte[] leftOver;
-
- private int currentLastBytePos;
-
- /**
- * ctor
- * @param no 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;
- final int dataLength = length + (leftOverOfLastFilePart != null ? leftOverOfLastFilePart.length : 0);
- this.data = new byte[dataLength];
- final long off = (no - 1) * blockSize;
-
- // read data
- if (no > 0 /* file not empty */) {
- channel.position(off);
- final int countRead = channel.read(ByteBuffer.wrap(data, 0, length));
- if (countRead != length) {
- throw new IllegalStateException("Count of requested bytes and actually read bytes don't match");
- }
- }
- // copy left over part into data arr
- if (leftOverOfLastFilePart != null) {
- System.arraycopy(leftOverOfLastFilePart, 0, data, length, leftOverOfLastFilePart.length);
- }
- this.currentLastBytePos = data.length - 1;
- this.leftOver = null;
- }
-
- /**
- * Handles block rollover
- *
- * @return the new FilePart or null
- * @throws IOException if there was a problem reading the file
- */
- private FilePart rollOver() throws IOException {
-
- if (currentLastBytePos > -1) {
- throw new IllegalStateException("Current currentLastCharPos unexpectedly positive... "
- + "last readLine() should have returned something! currentLastCharPos=" + currentLastBytePos);
- }
-
- if (no > 1) {
- return new FilePart(no - 1, blockSize, leftOver);
- }
- // NO 1 was the last FilePart, we're finished
- if (leftOver != null) {
- throw new IllegalStateException("Unexpected leftover of the last block: leftOverOfThisFilePart="
- + new String(leftOver, encoding));
- }
- return null;
- }
-
- /**
- * Reads a line.
- *
- * @return the line or null
- * @throws IOException if there is an error reading from the file
- */
- private String readLine() throws IOException {
-
- String line = null;
- int newLineMatchByteCount;
-
- final boolean isLastFilePart = no == 1;
-
- int i = currentLastBytePos;
- while (i > -1) {
-
- if (!isLastFilePart && i < avoidNewlineSplitBufferSize) {
- // avoidNewlineSplitBuffer: for all except the last file part we
- // take a few bytes to the next file part to avoid splitting of newlines
- createLeftOver();
- break; // skip last few bytes and leave it to the next file part
- }
-
- // --- check for newline ---
- if ((newLineMatchByteCount = getNewLineMatchByteCount(data, i)) > 0 /* found newline */) {
- final int lineStart = i + 1;
- final int lineLengthBytes = currentLastBytePos - lineStart + 1;
-
- if (lineLengthBytes < 0) {
- throw new IllegalStateException("Unexpected negative line length="+lineLengthBytes);
- }
- final byte[] lineData = new byte[lineLengthBytes];
- System.arraycopy(data, lineStart, lineData, 0, lineLengthBytes);
-
- line = new String(lineData, encoding);
-
- currentLastBytePos = i - newLineMatchByteCount;
- break; // found line
- }
-
- // --- move cursor ---
- i -= byteDecrement;
-
- // --- end of file part handling ---
- if (i < 0) {
- createLeftOver();
- break; // end of file part
- }
- }
-
- // --- last file part handling ---
- if (isLastFilePart && leftOver != null) {
- // there will be no line break anymore, this is the first line of the file
- line = new String(leftOver, encoding);
- leftOver = null;
- }
-
- return line;
- }
-
- /**
- * Creates the buffer containing any left over bytes.
- */
- private void createLeftOver() {
- final int lineLengthBytes = currentLastBytePos + 1;
- if (lineLengthBytes > 0) {
- // create left over for next block
- leftOver = new byte[lineLengthBytes];
- System.arraycopy(data, 0, leftOver, 0, lineLengthBytes);
- } else {
- leftOver = null;
- }
- currentLastBytePos = -1;
- }
-
- /**
- * Finds the new-line sequence and return its length.
- *
- * @param data buffer to scan
- * @param i start offset in buffer
- * @return length of newline sequence or 0 if none found
- */
- private int getNewLineMatchByteCount(final byte[] data, final int i) {
- for (final byte[] newLineSequence : newLineSequences) {
- boolean match = true;
- for (int j = newLineSequence.length - 1; j >= 0; j--) {
- final int k = i + j - (newLineSequence.length - 1);
- match &= k >= 0 && data[k] == newLineSequence[j];
- }
- if (match) {
- return newLineSequence.length;
- }
- }
- return 0;
- }
- }
-
}