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