/* * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.io; /** * This class is an input stream filter that provides the added * functionality of keeping track of the current line number. * <p> * A line is a sequence of bytes ending with a carriage return * character (<code>'\r'</code>), a newline character * (<code>'\n'</code>), or a carriage return character followed * immediately by a linefeed character. In all three cases, the line * terminating character(s) are returned as a single newline character. * <p> * The line number begins at <code>0</code>, and is incremented by * <code>1</code> when a <code>read</code> returns a newline character. * * @author Arthur van Hoff * @see java.io.LineNumberReader * @since JDK1.0 * @deprecated This class incorrectly assumes that bytes adequately represent * characters. As of JDK 1.1, the preferred way to operate on * character streams is via the new character-stream classes, which * include a class for counting line numbers. */ @Deprecated public class LineNumberInputStream extends FilterInputStream { int pushBack = -1; int lineNumber; int markLineNumber; int markPushBack = -1; /** * Constructs a newline number input stream that reads its input * from the specified input stream. * * @param in the underlying input stream. */ public LineNumberInputStream(InputStream in) { super(in); } /** * Reads the next byte of data from this input stream. The value * byte is returned as an <code>int</code> in the range * <code>0</code> to <code>255</code>. If no byte is available * because the end of the stream has been reached, the value * <code>-1</code> is returned. This method blocks until input data * is available, the end of the stream is detected, or an exception * is thrown. * <p> * The <code>read</code> method of * <code>LineNumberInputStream</code> calls the <code>read</code> * method of the underlying input stream. It checks for carriage * returns and newline characters in the input, and modifies the * current line number as appropriate. A carriage-return character or * a carriage return followed by a newline character are both * converted into a single newline character. * * @return the next byte of data, or <code>-1</code> if the end of this * stream is reached. * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in * @see java.io.LineNumberInputStream#getLineNumber() */ public int read() throws IOException { int c = pushBack; if (c != -1) { pushBack = -1; } else { c = in.read(); } switch (c) { case '\r': pushBack = in.read(); if (pushBack == '\n') { pushBack = -1; } case '\n': lineNumber++; return '\n'; } return c; } /** * Reads up to <code>len</code> bytes of data from this input stream * into an array of bytes. This method blocks until some input is available. * <p> * The <code>read</code> method of * <code>LineNumberInputStream</code> repeatedly calls the * <code>read</code> method of zero arguments to fill in the byte array. * * @param b the buffer into which the data is read. * @param off the start offset of the data. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or * <code>-1</code> if there is no more data because the end of * this stream has been reached. * @exception IOException if an I/O error occurs. * @see java.io.LineNumberInputStream#read() */ public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int c = read(); if (c == -1) { return -1; } b[off] = (byte)c; int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } if (b != null) { b[off + i] = (byte)c; } } } catch (IOException ee) { } return i; } /** * Skips over and discards <code>n</code> bytes of data from this * input stream. The <code>skip</code> method may, for a variety of * reasons, end up skipping over some smaller number of bytes, * possibly <code>0</code>. The actual number of bytes skipped is * returned. If <code>n</code> is negative, no bytes are skipped. * <p> * The <code>skip</code> method of <code>LineNumberInputStream</code> creates * a byte array and then repeatedly reads into it until * <code>n</code> bytes have been read or the end of the stream has * been reached. * * @param n the number of bytes to be skipped. * @return the actual number of bytes skipped. * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ public long skip(long n) throws IOException { int chunk = 2048; long remaining = n; byte data[]; int nr; if (n <= 0) { return 0; } data = new byte[chunk]; while (remaining > 0) { nr = read(data, 0, (int) Math.min(chunk, remaining)); if (nr < 0) { break; } remaining -= nr; } return n - remaining; } /** * Sets the line number to the specified argument. * * @param lineNumber the new line number. * @see #getLineNumber */ public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } /** * Returns the current line number. * * @return the current line number. * @see #setLineNumber */ public int getLineNumber() { return lineNumber; } /** * Returns the number of bytes that can be read from this input * stream without blocking. * <p> * Note that if the underlying input stream is able to supply * <i>k</i> input characters without blocking, the * <code>LineNumberInputStream</code> can guarantee only to provide * <i>k</i>/2 characters without blocking, because the * <i>k</i> characters from the underlying input stream might * consist of <i>k</i>/2 pairs of <code>'\r'</code> and * <code>'\n'</code>, which are converted to just * <i>k</i>/2 <code>'\n'</code> characters. * * @return the number of bytes that can be read from this input stream * without blocking. * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ public int available() throws IOException { return (pushBack == -1) ? super.available()/2 : super.available()/2 + 1; } /** * Marks the current position in this input stream. A subsequent * call to the <code>reset</code> method repositions this stream at * the last marked position so that subsequent reads re-read the same bytes. * <p> * The <code>mark</code> method of * <code>LineNumberInputStream</code> remembers the current line * number in a private variable, and then calls the <code>mark</code> * method of the underlying input stream. * * @param readlimit the maximum limit of bytes that can be read before * the mark position becomes invalid. * @see java.io.FilterInputStream#in * @see java.io.LineNumberInputStream#reset() */ public void mark(int readlimit) { markLineNumber = lineNumber; markPushBack = pushBack; in.mark(readlimit); } /** * Repositions this stream to the position at the time the * <code>mark</code> method was last called on this input stream. * <p> * The <code>reset</code> method of * <code>LineNumberInputStream</code> resets the line number to be * the line number at the time the <code>mark</code> method was * called, and then calls the <code>reset</code> method of the * underlying input stream. * <p> * Stream marks are intended to be used in * situations where you need to read ahead a little to see what's in * the stream. Often this is most easily done by invoking some * general parser. If the stream is of the type handled by the * parser, it just chugs along happily. If the stream is not of * that type, the parser should toss an exception when it fails, * which, if it happens within readlimit bytes, allows the outer * code to reset the stream and try another parser. * * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in * @see java.io.LineNumberInputStream#mark(int) */ public void reset() throws IOException { lineNumber = markLineNumber; pushBack = markPushBack; in.reset(); } }