com.ebmwebsourcing.easycommons.stream.ReaderInputStream Maven / Gradle / Ivy
/****************************************************************************
* Copyright (c) 2010-2012, EBM WebSourcing - All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the University of California, Berkeley nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
****************************************************************************/
package com.ebmwebsourcing.easycommons.stream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
public class ReaderInputStream extends InputStream {
/**
* The initial {@link Reader}.
*/
private Reader reader;
/**
* As a buffer reads from a Reader is bigger than a buffer reads from an
* InputStream, we need to keep characters read from the Reader and not
* returned to the client. They are stored in this buffer.
*
*/
private byte[] internalBuffer = null;
private int internalBufferPos = 0;
/**
* The constructor.
*
* @param reader
* The Reader to wrap. Not null.
*/
public ReaderInputStream(final Reader reader) {
if (reader == null) {
throw new IllegalArgumentException("Reader cannot be null.");
}
this.reader = reader;
}
/**
* Returns available bytes in the internal buffer incremented by one if the
* reader is ready (see {@link Reader#ready()}).
*
* @see java.io.InputStream#available()
*/
@Override
public int available() throws IOException {
if (this.reader.ready()) {
// A next read on the reader can be done withoutto be blocked.
// We do the read to check if a character is available or EOF is
// expected
final int availableChar = this.reader.read();
if (availableChar != -1) {
// We push the read character in the internal buffer
if (this.internalBuffer != null) {
final byte[] newBuffer = new byte[this.internalBuffer.length + 1];
System.arraycopy(this.internalBuffer, 0, newBuffer, 0,
this.internalBuffer.length);
newBuffer[newBuffer.length - 1] = (byte) availableChar;
this.internalBuffer = newBuffer;
} else {
this.internalBuffer = new String(new char[] { (char) availableChar })
.getBytes();
this.internalBufferPos = 0;
}
}
}
return this.internalBuffer == null ? 0
: (this.internalBuffer.length - this.internalBufferPos);
}
@Override
public void close() throws IOException {
this.reader.close();
}
@Override
public boolean markSupported() {
return false;
}
@Override
public int read() throws IOException {
byte[] buffer = new byte[1];
int nbByteRead = this.read(buffer);
if (nbByteRead != 1) {
throw new IOException("No byte read.");
}
return buffer[0];
}
@Override
public int read(final byte[] cbuf) throws IOException {
return this.read(cbuf, 0, cbuf.length);
}
@Override
public int read(final byte[] cbuf, final int off, final int len) throws IOException {
return this.localRead(cbuf, off, len, false);
}
@Override
public long skip(long n) throws IOException, IllegalArgumentException {
if (n > Long.MAX_VALUE) {
throw new IllegalArgumentException("Only value lesser " + Integer.MAX_VALUE
+ "are accepted.");
}
return this.localRead(null, 0, (int) n, true);
}
private int localRead(final byte[] buf, final int off, final int len, final boolean skip)
throws IOException {
int remainingLen = len;
int offset = off;
// First we read from the internal buffer
int bytesToReadInInternalBuffer = this.internalBuffer == null ? 0 : Math.min(len,
this.internalBuffer.length - this.internalBufferPos);
if (bytesToReadInInternalBuffer > 0) {
if (!skip) {
System.arraycopy(this.internalBuffer, this.internalBufferPos, buf, offset,
bytesToReadInInternalBuffer);
}
remainingLen -= bytesToReadInInternalBuffer;
this.internalBufferPos += bytesToReadInInternalBuffer;
}
if (remainingLen > 0) {
offset += bytesToReadInInternalBuffer;
// We must complete the provided buffer with bytes read from the
// reader
final char[] cbuf = new char[remainingLen];
int charRead = this.reader.read(cbuf, 0, remainingLen);
if (charRead == -1) {
// EOF: No more character in the reader
if (len == remainingLen) {
// No bytes available --> EOF
return -1;
} else {
// Few characters bytes have read from the internal buffer
return len - remainingLen;
}
} else {
this.internalBuffer = new String(cbuf, 0, charRead).getBytes();
this.internalBufferPos = 0;
bytesToReadInInternalBuffer = Math.min(remainingLen, charRead);
if (!skip) {
System.arraycopy(this.internalBuffer, 0, buf, offset,
bytesToReadInInternalBuffer);
}
this.internalBufferPos += bytesToReadInInternalBuffer;
// Now the provided buffer should be full
return bytesToReadInInternalBuffer;
}
} else {
// No more bytes to read, the provided buffer is full
return len;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy