InputStreamReaderpublic class InputStreamReader extends Reader A class for turning a byte stream into a character stream. Data read from the
source input stream is converted into characters by either a default or a
provided character converter. The default encoding is taken from the
"file.encoding" system property. {@code InputStreamReader} contains a buffer
of bytes read from the source stream and converts these into characters as
needed. The buffer size is 8K. |
Fields Summary |
---|
private InputStream | in | private static final int | BUFFER_SIZE | private boolean | endOfInput | CharsetDecoder | decoder | ByteBuffer | bytes |
Constructors Summary |
---|
public InputStreamReader(InputStream in)Constructs a new {@code InputStreamReader} on the {@link InputStream}
{@code in}. This constructor sets the character converter to the encoding
specified in the "file.encoding" property and falls back to ISO 8859_1
(ISO-Latin-1) if the property doesn't exist.
super(in);
this.in = in;
String encoding = AccessController
.doPrivileged(new PriviAction<String>(
"file.encoding", "ISO8859_1")); //$NON-NLS-1$//$NON-NLS-2$
decoder = Charset.forName(encoding).newDecoder().onMalformedInput(
CodingErrorAction.REPLACE).onUnmappableCharacter(
CodingErrorAction.REPLACE);
| public InputStreamReader(InputStream in, String enc)Constructs a new InputStreamReader on the InputStream {@code in}. The
character converter that is used to decode bytes into characters is
identified by name by {@code enc}. If the encoding cannot be found, an
UnsupportedEncodingException error is thrown.
super(in);
if (enc == null) {
throw new NullPointerException();
}
this.in = in;
try {
decoder = Charset.forName(enc).newDecoder().onMalformedInput(
CodingErrorAction.REPLACE).onUnmappableCharacter(
CodingErrorAction.REPLACE);
} catch (IllegalArgumentException e) {
throw new UnsupportedEncodingException();
}
| public InputStreamReader(InputStream in, CharsetDecoder dec)Constructs a new InputStreamReader on the InputStream {@code in} and
CharsetDecoder {@code dec}.
super(in);
dec.averageCharsPerByte();
this.in = in;
decoder = dec;
| public InputStreamReader(InputStream in, Charset charset)Constructs a new InputStreamReader on the InputStream {@code in} and
Charset {@code charset}.
super(in);
this.in = in;
decoder = charset.newDecoder().onMalformedInput(
CodingErrorAction.REPLACE).onUnmappableCharacter(
CodingErrorAction.REPLACE);
|
Methods Summary |
---|
public void | close()Closes this reader. This implementation closes the source InputStream and
releases all local storage.
synchronized (lock) {
// BEGIN android-added
if (decoder != null) {
decoder.reset();
}
// END android-added
decoder = null;
if (in != null) {
in.close();
in = null;
}
}
| public java.lang.String | getEncoding()Returns the name of the encoding used to convert bytes into characters.
The value {@code null} is returned if this reader has been closed.
if (!isOpen()) {
return null;
}
return HistoricalNamesUtil.getHistoricalName(decoder.charset().name());
| private boolean | isOpen()
return in != null;
| public int | read()Reads a single character from this reader and returns it as an integer
with the two higher-order bytes set to 0. Returns -1 if the end of the
reader has been reached. The byte value is either obtained from
converting bytes in this reader's buffer or by first filling the buffer
from the source InputStream and then reading from the buffer.
synchronized (lock) {
if (!isOpen()) {
// K0070=InputStreamReader is closed.
throw new IOException(Msg.getString("K0070")); //$NON-NLS-1$
}
char buf[] = new char[1];
return read(buf, 0, 1) != -1 ? buf[0] : -1;
}
| public int | read(char[] buf, int offset, int length)Reads at most {@code length} characters from this reader and stores them
at position {@code offset} in the character array {@code buf}. Returns
the number of characters actually read or -1 if the end of the reader has
been reached. The bytes are either obtained from converting bytes in this
reader's buffer or by first filling the buffer from the source
InputStream and then reading from the buffer.
synchronized (lock) {
if (!isOpen()) {
// K0070=InputStreamReader is closed.
throw new IOException(Msg.getString("K0070")); //$NON-NLS-1$
}
// BEGIN android-changed
// Exception priorities (in case of multiple errors) differ from
// RI, but are spec-compliant.
// made implicit null check explicit, used (offset | length) < 0
// instead of (offset < 0) || (length < 0) to safe one operation
if (buf == null) {
throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
}
if ((offset | length) < 0 || offset > buf.length - length) {
throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
}
// END android-changed
if (length == 0) {
return 0;
}
// allocate enough space for bytes if the default length is
// inadequate
int availableLen = in.available();
if (Math.min(availableLen, length) > bytes.capacity()) {
bytes = ByteBuffer.allocate(availableLen);
}
CharBuffer out = CharBuffer.wrap(buf, offset, length);
CoderResult result = CoderResult.UNDERFLOW;
byte[] a = bytes.array();
boolean has_been_read = false;
if (!bytes.hasRemaining() || bytes.limit() == bytes.capacity()) {
// Nothing is available in the buffer...
if (!bytes.hasRemaining()) {
bytes.clear();
}
int readed = in.read(a, bytes.arrayOffset(), bytes.remaining());
if (readed == -1) {
endOfInput = true;
return -1;
}
bytes.limit(readed);
has_been_read = true;
}
while (out.hasRemaining()) {
if (bytes.hasRemaining()) {
result = decoder.decode(bytes, out, false);
if (!bytes.hasRemaining() && endOfInput) {
decoder.decode(bytes, out, true);
decoder.flush(out);
decoder.reset();
break;
}
if (!out.hasRemaining()
|| bytes.position() == bytes.limit()) {
bytes.compact();
}
}
if (in.available() > 0
&& (!has_been_read && out.hasRemaining())
|| out.position() == 0) {
bytes.compact();
int to_read = bytes.remaining();
int off = bytes.arrayOffset() + bytes.position();
to_read = in.read(a, off, to_read);
if (to_read == -1) {
if (bytes.hasRemaining()) {
bytes.flip();
}
endOfInput = true;
break;
}
has_been_read = true;
if (to_read > 0) {
bytes.limit(bytes.position() + to_read);
bytes.position(0);
}
} else {
break;
}
}
if (result == CoderResult.UNDERFLOW && endOfInput) {
result = decoder.decode(bytes, out, true);
// FIXME: should flush at first, but seems ICU has a bug that it
// will throw IAE if some malform/unmappable bytes found during
// decoding
// result = decoder.flush(chars);
decoder.reset();
}
if (result.isMalformed()) {
throw new MalformedInputException(result.length());
} else if (result.isUnmappable()) {
throw new UnmappableCharacterException(result.length());
}
if (result == CoderResult.OVERFLOW && bytes.position() != 0) {
bytes.flip();
}
return out.position() - offset == 0 ? -1 : out.position() - offset;
}
| public boolean | ready()Indicates whether this reader is ready to be read without blocking. If
the result is {@code true}, the next {@code read()} will not block. If
the result is {@code false} then this reader may or may not block when
{@code read()} is called. This implementation returns {@code true} if
there are bytes available in the buffer or the source stream has bytes
available.
synchronized (lock) {
if (in == null) {
// K0070=InputStreamReader is closed.
throw new IOException(Msg.getString("K0070")); //$NON-NLS-1$
}
try {
return bytes.limit() != bytes.capacity() || in.available() > 0;
} catch (IOException e) {
return false;
}
}
|
|