home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / io / LineNumberInputStream.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  9.2 KB  |  275 lines

  1. /*
  2.  * @(#)LineNumberInputStream.java    1.17 98/03/18
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. /**
  18.  * This class is an input stream filter that provides the added 
  19.  * functionality of keeping track of the current line number. 
  20.  * <p>
  21.  * A line is a sequence of bytes ending with a carriage return 
  22.  * character (<code>'\r'</code>), a newline character 
  23.  * (<code>'\n'</code>), or a carriage return character followed 
  24.  * immediately by a linefeed character. In all three cases, the line 
  25.  * terminating character(s) are returned as a single newline character.
  26.  * <p>
  27.  * The line number begins at <code>0</code>, and is incremented by 
  28.  * <code>1</code> when a <code>read</code> returns a newline character.
  29.  *
  30.  * @author     Arthur van Hoff
  31.  * @version    1.17, 03/18/98
  32.  * @see        java.io.LineNumberReader
  33.  * @since      JDK1.0
  34.  * @deprecated This class incorrectly assumes that bytes adequately represent
  35.  *             characters.  As of JDK 1.1, the preferred way to operate on
  36.  *             character streams is via the new character-stream classes, which
  37.  *             include a class for counting line numbers.
  38.  */
  39. public
  40. class LineNumberInputStream extends FilterInputStream {
  41.     int pushBack = -1;
  42.     int lineNumber;
  43.     int markLineNumber;
  44.     int markPushBack = -1;
  45.     
  46.     /**
  47.      * Constructs a newline number input stream that reads its input 
  48.      * from the specified input stream. 
  49.      *
  50.      * @param      in   the underlying input stream.
  51.      */
  52.     public LineNumberInputStream(InputStream in) {
  53.     super(in);
  54.     }
  55.  
  56.     /**
  57.      * Reads the next byte of data from this input stream. The value 
  58.      * byte is returned as an <code>int</code> in the range 
  59.      * <code>0</code> to <code>255</code>. If no byte is available 
  60.      * because the end of the stream has been reached, the value 
  61.      * <code>-1</code> is returned. This method blocks until input data 
  62.      * is available, the end of the stream is detected, or an exception 
  63.      * is thrown. 
  64.      * <p>
  65.      * The <code>read</code> method of 
  66.      * <code>LineNumberInputStream</code> calls the <code>read</code> 
  67.      * method of the underlying input stream. It checks for carriage 
  68.      * returns and newline characters in the input, and modifies the 
  69.      * current line number as appropriate. A carriage-return character or 
  70.      * a carriage return followed by a newline character are both 
  71.      * converted into a single newline character. 
  72.      *
  73.      * @return     the next byte of data, or <code>-1</code> if the end of this
  74.      *             stream is reached.
  75.      * @exception  IOException  if an I/O error occurs.
  76.      * @see        java.io.FilterInputStream#in
  77.      * @see        java.io.LineNumberInputStream#getLineNumber()
  78.      */
  79.     public int read() throws IOException {
  80.     int c = pushBack;
  81.  
  82.     if (c != -1) {
  83.         pushBack = -1;
  84.     } else {
  85.         c = in.read();
  86.     }
  87.  
  88.     switch (c) {
  89.       case '\r':
  90.         pushBack = in.read();
  91.         if (pushBack == '\n') {
  92.         pushBack = -1;
  93.         }
  94.       case '\n':
  95.         lineNumber++;
  96.         return '\n';
  97.     }
  98.     return c;
  99.     }
  100.  
  101.     /**
  102.      * Reads up to <code>len</code> bytes of data from this input stream 
  103.      * into an array of bytes. This method blocks until some input is available.
  104.      * <p>
  105.      * The <code>read</code> method of 
  106.      * <code>LineNumberInputStream</code> repeatedly calls the 
  107.      * <code>read</code> method of zero arguments to fill in the byte array.
  108.      *
  109.      * @param      b     the buffer into which the data is read.
  110.      * @param      off   the start offset of the data.
  111.      * @param      len   the maximum number of bytes read.
  112.      * @return     the total number of bytes read into the buffer, or
  113.      *             <code>-1</code> if there is no more data because the end of
  114.      *             this stream has been reached.
  115.      * @exception  IOException  if an I/O error occurs.
  116.      * @see        java.io.LineNumberInputStream#read()
  117.      */
  118.     public int read(byte b[], int off, int len) throws IOException {
  119.     if (len <= 0) {
  120.         return 0;
  121.     }
  122.  
  123.     int c = read();
  124.     if (c == -1) {
  125.         return -1;
  126.     }
  127.     b[off] = (byte)c;
  128.  
  129.     int i = 1;
  130.     try {
  131.         for (; i < len ; i++) {
  132.         c = read();
  133.         if (c == -1) {
  134.             break;
  135.         }
  136.         if (b != null) {
  137.             b[off + i] = (byte)c;
  138.         }
  139.         }
  140.     } catch (IOException ee) {
  141.     }
  142.     return i;
  143.     }
  144.  
  145.     /**
  146.      * Skips over and discards <code>n</code> bytes of data from this 
  147.      * input stream. The <code>skip</code> method may, for a variety of 
  148.      * reasons, end up skipping over some smaller number of bytes, 
  149.      * possibly <code>0</code>. The actual number of bytes skipped is 
  150.      * returned.  If <code>n</code> is negative, no bytes are skipped.
  151.      * <p>
  152.      * The <code>skip</code> method of <code>LineNumberInputStream</code> creates 
  153.      * a byte array and then repeatedly reads into it until 
  154.      * <code>n</code> bytes have been read or the end of the stream has 
  155.      * been reached. 
  156.      *
  157.      * @param      n   the number of bytes to be skipped.
  158.      * @return     the actual number of bytes skipped.
  159.      * @exception  IOException  if an I/O error occurs.
  160.      * @see        java.io.FilterInputStream#in
  161.      */
  162.     public long skip(long n) throws IOException {
  163.     int chunk = 2048;             
  164.     long remaining = n;
  165.     byte data[];
  166.     int nr;
  167.  
  168.     if (n <= 0) {
  169.         return 0;
  170.     }
  171.     
  172.     data = new byte[chunk];
  173.     while (remaining > 0) {
  174.         nr = read(data, 0, (int) Math.min(chunk, remaining));
  175.         if (nr < 0) {
  176.         break;
  177.         }
  178.         remaining -= nr;
  179.     }
  180.     
  181.     return n - remaining;
  182.     }
  183.  
  184.     /**
  185.      * Sets the line number to the specified argument. 
  186.      *
  187.      * @param      lineNumber   the new line number.
  188.      */
  189.     public void setLineNumber(int lineNumber) {
  190.     this.lineNumber = lineNumber;
  191.     }
  192.  
  193.     /**
  194.      * Returns the current line number.
  195.      *
  196.      * @return     the current line number.
  197.      */
  198.     public int getLineNumber() {
  199.     return lineNumber;
  200.     }
  201.  
  202.    
  203.     /**
  204.      * Returns the number of bytes that can be read from this input 
  205.      * stream without blocking. 
  206.      * <p>
  207.      * Note that if the underlying input stream is able to supply 
  208.      * <i>k</i> input characters without blocking, the 
  209.      * <code>LineNumberInputStream</code> can guarantee only to provide 
  210.      * <i>k</i>/2 characters without blocking, because the 
  211.      * <i>k</i> characters from the underlyhing input stream might 
  212.      * consist of <i>k</i>/2 pairs of <code>'\r'</code> and 
  213.      * <code>'\n'</code>, which are converted to just 
  214.      * <i>k</i>/2 <code>'\n'</code> characters. 
  215.      *
  216.      * @return     the number of bytes that can be read from this input stream
  217.      *             without blocking.
  218.      * @exception  IOException  if an I/O error occurs.
  219.      * @see        java.io.FilterInputStream#in
  220.      */
  221.     public int available() throws IOException {
  222.     return (pushBack == -1) ? super.available()/2 : super.available()/2 + 1;
  223.     }
  224.  
  225.     /**
  226.      * Marks the current position in this input stream. A subsequent 
  227.      * call to the <code>reset</code> method repositions this stream at 
  228.      * the last marked position so that subsequent reads re-read the same bytes.
  229.      * <p>
  230.      * The <code>mark</code> method of 
  231.      * <code>LineNumberInputStream</code> remembers the current line 
  232.      * number in a private variable, and then calls the <code>mark</code> 
  233.      * method of the underlying input stream. 
  234.      *
  235.      * @param   readlimit   the maximum limit of bytes that can be read before
  236.      *                      the mark position becomes invalid.
  237.      * @see     java.io.FilterInputStream#in
  238.      * @see     java.io.LineNumberInputStream#reset()
  239.      */
  240.     public void mark(int readlimit) {
  241.     markLineNumber = lineNumber;
  242.         markPushBack   = pushBack;
  243.     in.mark(readlimit);
  244.     }
  245.  
  246.     /**
  247.      * Repositions this stream to the position at the time the 
  248.      * <code>mark</code> method was last called on this input stream. 
  249.      * <p>
  250.      * The <code>reset</code> method of 
  251.      * <code>LineNumberInputStream</code> resets the line number to be 
  252.      * the line number at the time the <code>mark</code> method was 
  253.      * called, and then calls the <code>reset</code> method of the 
  254.      * underlying input stream. 
  255.      * <p>
  256.      * Stream marks are intended to be used in
  257.      * situations where you need to read ahead a little to see what's in
  258.      * the stream. Often this is most easily done by invoking some
  259.      * general parser. If the stream is of the type handled by the
  260.      * parser, it just chugs along happily. If the stream is not of
  261.      * that type, the parser should toss an exception when it fails,
  262.      * which, if it happens within readlimit bytes, allows the outer
  263.      * code to reset the stream and try another parser.
  264.      *
  265.      * @exception  IOException  if an I/O error occurs.
  266.      * @see        java.io.FilterInputStream#in
  267.      * @see        java.io.LineNumberInputStream#mark(int)
  268.      */
  269.     public void reset() throws IOException {
  270.     lineNumber = markLineNumber;
  271.         pushBack   = markPushBack;
  272.     in.reset();
  273.     }
  274. }
  275.