summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java')
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java b/src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java
new file mode 100644
index 00000000..115a5df6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/io/LineReader.java
@@ -0,0 +1,122 @@
+package de.lmu.ifi.dbs.elki.utilities.io;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2014
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+/**
+ * Fast class to read a file, line per line.
+ *
+ * Lines must be split using Unix newlines <code>\n</code>, linefeeds
+ * <code>\r</code> are ignored.
+ *
+ * This is a rather minimal implementation, which supposedly pays off in
+ * performance. In particular, this class allows recycling the buffer, which
+ * will yield less object allocations and thus less garbage collection.
+ *
+ * Usage example:
+ *
+ * <pre>
+ * StringBuilder buf = new StringBuilder();
+ * LineReader reader = new LineReader(inputStream);
+ * // Clear buffer, and append next line.
+ * while(reader.readLine(buf.delete(0, buf.length()))) {
+ * // process string in buffer.
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+public class LineReader implements AutoCloseable {
+ /** Buffer size to use */
+ final static int BUFFER_SIZE = 4096;
+
+ /** Input stream to read from */
+ Reader in;
+
+ /** Character buffer */
+ char[] buffer = new char[BUFFER_SIZE];
+
+ /** Current position, and length of buffer */
+ int pos = 0, end = 0;
+
+ /**
+ * Constructor
+ *
+ * @param in Stream
+ */
+ public LineReader(InputStream in) {
+ this(new InputStreamReader(in));
+ }
+
+ /**
+ * Constructor
+ *
+ * @param in Reader
+ */
+ public LineReader(Reader in) {
+ this.in = in;
+ }
+
+ /**
+ * Read a line into the given buffer.
+ *
+ * @param buf Buffer.
+ * @return {@code true} if some characters have been read.
+ */
+ public boolean readLine(Appendable buf) throws IOException {
+ boolean success = false;
+ while(true) {
+ // Process buffer:
+ while(pos < end) {
+ success = true;
+ final char c = buffer[pos++];
+ if(c == '\n') {
+ return success;
+ }
+ if(c == '\r') {
+ continue;
+ }
+ buf.append(c);
+ }
+ // Refill buffer:
+ assert (pos >= end) : "Buffer wasn't empty when refilling!";
+ end = in.read(buffer, 0, buffer.length);
+ pos = 0;
+ if(end < 0) { // End of stream.
+ return success;
+ }
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ if(in != null) {
+ in.close();
+ }
+ }
+}