diff options
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.java | 122 |
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(); + } + } +} |