LineNumberInputStream.java revision fdb2704414a9ed92394ada0d1395e4db86889465
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.io; 19 20/** 21 * LineNumberInputStream is a filter class which counts the number of line 22 * terminators from the data read from the target InputStream. A line delimiter 23 * sequence is determined by '\r', '\n', or '\r\n'. When using <code>read</code>, 24 * the sequence is always translated into '\n'. 25 * 26 * @deprecated Use {@link LineNumberReader} 27 */ 28@Deprecated 29public class LineNumberInputStream extends FilterInputStream { 30 31 private int lineNumber; 32 33 private int markedLineNumber = -1; 34 35 private int lastChar = -1; 36 37 private int markedLastChar; 38 39 /** 40 * Constructs a new LineNumberInputStream on the InputStream <code>in</code>. 41 * All reads are now filtered through this stream and line numbers will be 42 * counted for all data read from this Stream. 43 * 44 * @param in 45 * The non-null InputStream to count line numbers. 46 */ 47 public LineNumberInputStream(InputStream in) { 48 super(in); 49 } 50 51 /** 52 * Returns a int representing the number of bytes that are available before 53 * this LineNumberInputStream will block. This method returns the number of 54 * bytes available in the target stream. Since the target input stream may 55 * just be a sequence of <code>\r\n</code> characters and this filter only 56 * returns <code>\n<code> then <code>available</code> can only 57 * guarantee <code>target.available()/2</code> characters. 58 * 59 * @return int the number of bytes available before blocking. 60 * 61 * @throws IOException If an error occurs in this stream. 62 */ 63 @Override 64 public int available() throws IOException { 65 return in.available() / 2 + (lastChar == -1 ? 0 : 1); 66 } 67 68 /** 69 * Returns a int representing the current line number for this 70 * LineNumberInputStream. 71 * 72 * @return int the current line number. 73 */ 74 public int getLineNumber() { 75 return lineNumber; 76 } 77 78 /** 79 * Set a Mark position in this LineNumberInputStream. The parameter 80 * <code>readLimit</code> indicates how many bytes can be read before a 81 * mark is invalidated. Sending reset() will reposition the Stream back to 82 * the marked position provided <code>readLimit</code> has not been 83 * surpassed. The lineNumber count will also be reset to the last marked 84 * lineNumber count. 85 * <p> 86 * This implementation sets a mark in the target stream. 87 * 88 * @param readlimit 89 * The number of bytes to be able to read before invalidating the 90 * mark. 91 */ 92 @Override 93 public void mark(int readlimit) { 94 in.mark(readlimit); 95 markedLineNumber = lineNumber; 96 markedLastChar = lastChar; 97 } 98 99 /** 100 * Reads a single byte from this LineNumberInputStream and returns the 101 * result as an int. The low-order byte is returned or -1 of the end of 102 * stream was encountered. This implementation returns a byte from the 103 * target stream. The line number count is incremented if a line terminator 104 * is encountered. A line delimiter sequence is determined by '\r', '\n', or 105 * '\r\n'. In this method, the sequence is always translated into '\n'. 106 * 107 * @return int The byte read or -1 if end of stream. 108 * 109 * @throws IOException 110 * If the stream is already closed or another IOException 111 * occurs. 112 */ 113 @Override 114 public int read() throws IOException { 115 int currentChar = lastChar; 116 if (currentChar == -1) { 117 currentChar = in.read(); 118 } else { 119 lastChar = -1; 120 } 121 switch (currentChar) { 122 case '\r': 123 currentChar = '\n'; 124 lastChar = in.read(); 125 if (lastChar == '\n') { 126 lastChar = -1; 127 } 128 // fall through 129 case '\n': 130 lineNumber++; 131 } 132 return currentChar; 133 } 134 135 /** 136 * Reads at most <code>length</code> bytes from this LineNumberInputStream 137 * and stores them in byte array <code>buffer</code> starting at 138 * <code>offset</code>. Answer the number of bytes actually read or -1 if 139 * no bytes were read and end of stream was encountered. This implementation 140 * reads bytes from the target stream. The line number count is incremented 141 * if a line terminator is encountered. A line delimiter sequence is 142 * determined by '\r', '\n', or '\r\n'. In this method, the sequence is 143 * always translated into '\n'. 144 * 145 * @param buffer 146 * the non-null byte array in which to store the read bytes. 147 * @param offset 148 * the offset in <code>buffer</code> to store the read bytes. 149 * @param length 150 * the maximum number of bytes to store in <code>buffer</code>. 151 * @return The number of bytes actually read or -1 if end of stream. 152 * 153 * @throws IOException 154 * If the stream is already closed or another IOException 155 * occurs. 156 * @throws NullPointerException 157 * If <code>buffer</code> is <code>null</code>. 158 * @throws IllegalArgumentException 159 * If <code>offset</code> or <code>count</code> are out of 160 * bounds. 161 */ 162 @Override 163 public int read(byte[] buffer, int offset, int length) throws IOException { 164 if (buffer == null) { 165 throw new NullPointerException(); 166 } 167 // avoid int overflow 168 if (offset < 0 || offset > buffer.length || length < 0 169 || length > buffer.length - offset) { 170 throw new ArrayIndexOutOfBoundsException(); 171 } 172 173 for (int i = 0; i < length; i++) { 174 int currentChar; 175 try { 176 currentChar = read(); 177 } catch (IOException e) { 178 if (i != 0) { 179 return i; 180 } 181 throw e; 182 } 183 if (currentChar == -1) { 184 return i == 0 ? -1 : i; 185 } 186 buffer[offset + i] = (byte) currentChar; 187 } 188 return length; 189 } 190 191 /** 192 * Reset this LineNumberInputStream to the last marked location. If the 193 * <code>readlimit</code> has been passed or no <code>mark</code> has 194 * been set, throw IOException. This implementation resets the target 195 * stream. It also resets the line count to what is was when this Stream was 196 * marked. 197 * 198 * @throws IOException 199 * If the stream is already closed or another IOException 200 * occurs. 201 */ 202 @Override 203 public void reset() throws IOException { 204 in.reset(); 205 lineNumber = markedLineNumber; 206 lastChar = markedLastChar; 207 } 208 209 /** 210 * Sets the lineNumber of this LineNumberInputStream to the specified 211 * <code>lineNumber</code>. Note that this may have side effects on the 212 * line number associated with the last marked position. 213 * 214 * @param lineNumber 215 * the new lineNumber value. 216 */ 217 public void setLineNumber(int lineNumber) { 218 this.lineNumber = lineNumber; 219 } 220 221 /** 222 * Skips <code>count</code> number of bytes in this InputStream. 223 * Subsequent <code>read()</code>'s will not return these bytes unless 224 * <code>reset()</code> is used. This implementation skips 225 * <code>count</code> number of bytes in the target stream and increments 226 * the lineNumber count as bytes are skipped. 227 * 228 * @param count 229 * the number of bytes to skip. 230 * @return the number of bytes actually skipped. 231 * 232 * @throws IOException 233 * If the stream is already closed or another IOException 234 * occurs. 235 */ 236 @Override 237 public long skip(long count) throws IOException { 238 if (count <= 0) { 239 return 0; 240 } 241 for (int i = 0; i < count; i++) { 242 int currentChar = read(); 243 if (currentChar == -1) { 244 return i; 245 } 246 } 247 return count; 248 } 249} 250