Java tutorial
/* * Copyright 2011 Oliver Schrenk * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.oschrenk.flatfiles.util; import java.io.BufferedReader; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; import com.google.common.base.Predicate; import com.google.common.base.Predicates; /** * This class takes a {@link Reader} and a {@link Predicate} and keeps lines to * which the predicate applies. Line terminators are converted to a * <code>\n</code>. * * @author Oliver Schrenk <oliver.schrenk@gmail.com> */ public class PredicateFilterReader extends FilterReader { /** * The current line. If null and emitNewline is false, a newline must be * fetched. */ private String currentLine; /** * The index of the first unread character in curLine. If at any time * <code>curLineIx == curLine.length</code>, <code>currentLine</code> is set * to <code>null</code>. */ int currentLineIndex; /** * If <code>true</code>, the newline at the end of currentLine has not been * returned. * * It would have been more convenient to append the newline onto freshly * fetched lines. However, that would incur another allocation and copy. */ boolean emitNewline; /** The buffered reader. */ private final BufferedReader bufferedReader; /** The line predicate. */ private final Predicate<String> linePredicate; /** * Instantiates a new comment filter reader. * * @param in * the in */ protected PredicateFilterReader(final Reader in) { super(in); bufferedReader = new BufferedReader(in); linePredicate = Predicates.alwaysTrue(); } /** * Instantiates a new comment filter reader. * * @param in * the reader * @param linePredicate * the line predicate */ public PredicateFilterReader(final Reader in, final Predicate<String> linePredicate) { super(in); bufferedReader = new BufferedReader(in); this.linePredicate = linePredicate; } @Override public int read() throws IOException { final char[] chars = new char[1]; final int read = read(chars, 0, 1); if (read == -1) { return -1; } return chars[0]; } /* * (non-Javadoc) * * @see java.io.FilterReader#read(char[], int, int) */ @Override public int read(final char cbuf[], int off, final int len) throws IOException { // Fetch new line if necessary if (currentLine == null && !emitNewline) { setNextMatchingLine(); } // Return characters from current line if (currentLine != null) { int num = Math.min(len, Math.min(cbuf.length - off, currentLine.length() - currentLineIndex)); // Copy characters from curLine to cbuf for (int i = 0; i < num; i++) { cbuf[off++] = currentLine.charAt(currentLineIndex++); } // No more characters in curLine if (currentLineIndex == currentLine.length()) { currentLine = null; // Is there room for the newline? if (num < len && off < cbuf.length) { cbuf[off++] = '\n'; emitNewline = false; num++; } } // Return number of character read return num; } else if (emitNewline && len > 0) { // Emit just the newline cbuf[off] = '\n'; emitNewline = false; return 1; } else if (len > 0) { // No more characters left in input reader return -1; } else { // Client did not ask for any characters return 0; } } /** * Gets the next line. * * @throws IOException * Signals that an I/O exception has occurred. */ private void setNextMatchingLine() throws IOException { currentLine = bufferedReader.readLine(); while (currentLine != null) { if (linePredicate.apply(currentLine)) { emitNewline = true; currentLineIndex = 0; return; } currentLine = bufferedReader.readLine(); } } /* * (non-Javadoc) * * @see java.io.FilterReader#ready() */ @Override public boolean ready() throws IOException { return currentLine != null || emitNewline || in.ready(); } /* * (non-Javadoc) * * @see java.io.FilterReader#markSupported() */ @Override public boolean markSupported() { return false; } @Override public void close() throws IOException { bufferedReader.close(); super.close(); } }