1 |
/* |
/* |
2 |
* $Id$ |
* LineInputStream.java |
3 |
* Copyright (C) 2002 The Free Software Foundation |
* Copyright (C) 2002 The Free Software Foundation |
4 |
* |
* |
5 |
* This file is part of GNU inetlib, a library. |
* This file is part of GNU inetlib, a library. |
47 |
* An input stream that can read lines of input. |
* An input stream that can read lines of input. |
48 |
* |
* |
49 |
* @author <a href="mailto:dog@gnu.org">Chris Burdess</a> |
* @author <a href="mailto:dog@gnu.org">Chris Burdess</a> |
|
* @version $Revision$ $Date$ |
|
50 |
*/ |
*/ |
51 |
public class LineInputStream extends FilterInputStream |
public class LineInputStream |
52 |
|
extends FilterInputStream |
53 |
{ |
{ |
54 |
|
|
55 |
/* |
/* |
76 |
* Constructor using the US-ASCII character encoding. |
* Constructor using the US-ASCII character encoding. |
77 |
* @param in the underlying input stream |
* @param in the underlying input stream |
78 |
*/ |
*/ |
79 |
public LineInputStream (InputStream in) |
public LineInputStream(InputStream in) |
80 |
{ |
{ |
81 |
this (in, "US-ASCII"); |
this(in, "US-ASCII"); |
82 |
} |
} |
83 |
|
|
84 |
/** |
/** |
86 |
* @param in the underlying input stream |
* @param in the underlying input stream |
87 |
* @param encoding the character encoding to use |
* @param encoding the character encoding to use |
88 |
*/ |
*/ |
89 |
public LineInputStream (InputStream in, String encoding) |
public LineInputStream(InputStream in, String encoding) |
90 |
{ |
{ |
91 |
super (in); |
super(in); |
92 |
buf = new ByteArrayOutputStream (); |
buf = new ByteArrayOutputStream(); |
93 |
this.encoding = encoding; |
this.encoding = encoding; |
94 |
eof = false; |
eof = false; |
95 |
blockReads = in.markSupported (); |
blockReads = in.markSupported(); |
96 |
} |
} |
97 |
|
|
98 |
/** |
/** |
99 |
* Read a line of input. |
* Read a line of input. |
100 |
*/ |
*/ |
101 |
public String readLine () |
public String readLine() |
102 |
throws IOException |
throws IOException |
103 |
{ |
{ |
104 |
if (eof) |
if (eof) |
113 |
final int MIN_LENGTH = 1024; |
final int MIN_LENGTH = 1024; |
114 |
int len, pos; |
int len, pos; |
115 |
|
|
116 |
len = in.available (); |
len = in.available(); |
117 |
len = (len < MIN_LENGTH) ? MIN_LENGTH : len; |
len = (len < MIN_LENGTH) ? MIN_LENGTH : len; |
118 |
byte[] b = new byte[len]; |
byte[] b = new byte[len]; |
119 |
in.mark (len); |
in.mark(len); |
120 |
// Read into buffer b |
// Read into buffer b |
121 |
len = in.read (b, 0, len); |
len = in.read(b, 0, len); |
122 |
// Handle EOF |
// Handle EOF |
123 |
if (len == -1) |
if (len == -1) |
124 |
{ |
{ |
125 |
eof = true; |
eof = true; |
126 |
if (buf.size () == 0) |
if (buf.size() == 0) |
127 |
{ |
{ |
128 |
return null; |
return null; |
129 |
} |
} |
130 |
else |
else |
131 |
{ |
{ |
132 |
// We don't care about resetting buf |
// We don't care about resetting buf |
133 |
return buf.toString (encoding); |
return buf.toString(encoding); |
134 |
} |
} |
135 |
} |
} |
136 |
// Get index of LF in b |
// Get index of LF in b |
137 |
pos = indexOf (b, len, (byte) 0x0a); |
pos = indexOf(b, len, (byte) 0x0a); |
138 |
if (pos != -1) |
if (pos != -1) |
139 |
{ |
{ |
140 |
// Write pos bytes to buf |
// Write pos bytes to buf |
141 |
buf.write (b, 0, pos); |
buf.write(b, 0, pos); |
142 |
// Reset stream, and read pos + 1 bytes |
// Reset stream, and read pos + 1 bytes |
143 |
in.reset (); |
in.reset(); |
144 |
pos += 1; |
pos += 1; |
145 |
while (pos > 0) |
while (pos > 0) |
146 |
{ |
{ |
147 |
len = in.read (b, 0, pos); |
len = in.read(b, 0, pos); |
148 |
pos -= len; |
pos -= len; |
149 |
} |
} |
150 |
// Return line |
// Return line |
151 |
String ret = buf.toString (encoding); |
String ret = buf.toString(encoding); |
152 |
buf.reset (); |
buf.reset(); |
153 |
return ret; |
return ret; |
154 |
} |
} |
155 |
else |
else |
156 |
{ |
{ |
157 |
// Append everything to buf and fall through to re-read. |
// Append everything to buf and fall through to re-read. |
158 |
buf.write (b, 0, len); |
buf.write(b, 0, len); |
159 |
} |
} |
160 |
} |
} |
161 |
else |
else |
162 |
{ |
{ |
163 |
// We must use character reads in order not to read too much |
// We must use character reads in order not to read too much |
164 |
// from the underlying stream. |
// from the underlying stream. |
165 |
int c = in.read (); |
int c = in.read(); |
166 |
switch (c) |
switch (c) |
167 |
{ |
{ |
168 |
case -1: |
case -1: |
169 |
eof = true; |
eof = true; |
170 |
if (buf.size () == 0) |
if (buf.size() == 0) |
171 |
{ |
{ |
172 |
return null; |
return null; |
173 |
} |
} |
174 |
// Fall through and return contents of buffer. |
// Fall through and return contents of buffer. |
175 |
case 0x0a: // LF |
case 0x0a: // LF |
176 |
String ret = buf.toString (encoding); |
String ret = buf.toString(encoding); |
177 |
buf.reset (); |
buf.reset(); |
178 |
return ret; |
return ret; |
179 |
default: |
default: |
180 |
buf.write (c); |
buf.write(c); |
181 |
} |
} |
182 |
} |
} |
183 |
} |
} |
184 |
while (true); |
while (true); |
185 |
} |
} |
186 |
|
|
187 |
private int indexOf (byte[] b, int len, byte c) |
private int indexOf(byte[] b, int len, byte c) |
188 |
{ |
{ |
189 |
for (int pos = 0; pos < len; pos++) |
for (int pos = 0; pos < len; pos++) |
190 |
{ |
{ |
197 |
} |
} |
198 |
|
|
199 |
} |
} |
200 |
|
|