SharedFileInputStreampublic class SharedFileInputStream extends BufferedInputStream implements SharedInputStreamA SharedFileInputStream is a
BufferedInputStream that buffers
data from the file and supports the mark
and reset methods. It also supports the
newStream method that allows you to create
other streams that represent subsets of the file.
A RandomAccessFile object is used to
access the file data.
Note that when the SharedFileInputStream is closed,
all streams created with the newStream
method are also closed. This allows the creator of the
SharedFileInputStream object to control access to the
underlying file and ensure that it is closed when
needed, to avoid leaking file descriptors. Note also
that this behavior contradicts the requirements of
SharedInputStream and may change in a future release. |
Fields Summary |
---|
private static int | defaultBufferSize | protected RandomAccessFile | inThe file containing the data.
Shared by all related SharedFileInputStreams. | protected int | bufsizeThe normal size of the read buffer. | protected long | bufposThe file offset that corresponds to the first byte in
the read buffer. | protected long | startThe file offset of the start of data in this subset of the file. | protected long | datalenThe amount of data in this subset of the file. | private boolean | masterTrue if this is a top level stream created directly by "new".
False if this is a derived stream created by newStream. | private SharedFile | sf |
Constructors Summary |
---|
public SharedFileInputStream(File file)Creates a SharedFileInputStream
for the file.
this(file, defaultBufferSize);
| public SharedFileInputStream(String file)Creates a SharedFileInputStream
for the named file
this(file, defaultBufferSize);
| public SharedFileInputStream(File file, int size)Creates a SharedFileInputStream
with the specified buffer size.
super(null); // XXX - will it NPE?
if (size <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
init(new SharedFile(file), size);
| public SharedFileInputStream(String file, int size)Creates a SharedFileInputStream
with the specified buffer size.
super(null); // XXX - will it NPE?
if (size <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
init(new SharedFile(file), size);
| private SharedFileInputStream(SharedFile sf, long start, long len, int bufsize)Used internally by the newStream method.
super(null);
this.master = false;
this.sf = sf;
this.in = sf.open();
this.start = start;
this.bufpos = start;
this.datalen = len;
this.bufsize = bufsize;
buf = new byte[bufsize];
|
Methods Summary |
---|
public synchronized int | available()Returns the number of bytes that can be read from this input
stream without blocking.
ensureOpen();
return (count - pos) + in_available();
| public void | close()Closes this input stream and releases any system resources
associated with the stream.
if (in == null)
return;
try {
if (master)
sf.forceClose();
else
sf.close();
} finally {
sf = null;
in = null;
buf = null;
}
| private void | ensureOpen()Check to make sure that this stream has not been closed
if (in == null)
throw new IOException("Stream closed");
| private void | fill()Fills the buffer with more data, taking into account
shuffling and other tricks for dealing with marks.
Assumes that it is being called by a synchronized method.
This method also assumes that all data has already been read in,
hence pos > count.
if (markpos < 0) {
pos = 0; /* no mark: throw away the buffer */
bufpos += count;
} else if (pos >= buf.length) /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
int sz = pos - markpos;
System.arraycopy(buf, markpos, buf, 0, sz);
pos = sz;
bufpos += markpos;
markpos = 0;
} else if (buf.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
bufpos += count;
} else { /* grow buffer */
int nsz = pos * 2;
if (nsz > marklimit)
nsz = marklimit;
byte nbuf[] = new byte[nsz];
System.arraycopy(buf, 0, nbuf, 0, pos);
buf = nbuf;
}
count = pos;
in.seek(bufpos + pos);
// limit to datalen
int len = buf.length - pos;
if (bufpos - start + pos + len > datalen)
len = (int)(datalen - (bufpos - start + pos));
int n = in.read(buf, pos, len);
if (n > 0)
count = n + pos;
| protected void | finalize()Force this stream to close.
super.finalize();
close();
| public long | getPosition()Return the current position in the InputStream, as an
offset from the beginning of the InputStream.
//System.out.println("getPosition: start " + start + " pos " + pos + " bufpos " + bufpos + " = " + (bufpos + pos - start));
if (in == null)
throw new RuntimeException("Stream closed");
return bufpos + pos - start;
| private int | in_available()
// XXX - overflow
return (int)((start + datalen) - (bufpos + count));
| private void | init(javax.mail.util.SharedFileInputStream$SharedFile sf, int size)
this.sf = sf;
this.in = sf.open();
this.start = 0;
this.datalen = in.length(); // XXX - file can't grow
this.bufsize = size;
buf = new byte[size];
| public synchronized void | mark(int readlimit)See the general contract of the mark
method of InputStream .
marklimit = readlimit;
markpos = pos;
| public boolean | markSupported()Tests if this input stream supports the mark
and reset methods. The markSupported
method of SharedFileInputStream returns
true .
return true;
| public java.io.InputStream | newStream(long start, long end)Return a new InputStream representing a subset of the data
from this InputStream, starting at start (inclusive)
up to end (exclusive). start must be
non-negative. If end is -1, the new stream ends
at the same place as this stream. The returned InputStream
will also implement the SharedInputStream interface.
if (in == null)
throw new RuntimeException("Stream closed");
if (start < 0)
throw new IllegalArgumentException("start < 0");
if (end == -1)
end = datalen;
return new SharedFileInputStream(sf,
this.start + (int)start, (int)(end - start), bufsize);
| public synchronized int | read(byte[] b, int off, int len)Reads bytes from this stream into the specified byte array,
starting at the given offset.
This method implements the general contract of the corresponding
{@link java.io.InputStream#read(byte[], int, int) read}
method of the {@link java.io.InputStream} class.
ensureOpen();
if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int n = read1(b, off, len);
if (n <= 0) return n;
while ((n < len) /* && (in.available() > 0) */) {
int n1 = read1(b, off + n, len - n);
if (n1 <= 0) break;
n += n1;
}
return n;
| public synchronized int | read()See the general contract of the read
method of InputStream .
ensureOpen();
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return buf[pos++] & 0xff;
| private int | read1(byte[] b, int off, int len)Read characters into a portion of an array, reading from the underlying
stream at most once if necessary.
int avail = count - pos;
if (avail <= 0) {
if (false) {
/* If the requested length is at least as large as the buffer, and
if there is no mark/reset activity, do not bother to copy the
bytes into the local buffer. In this way buffered streams will
cascade harmlessly. */
if (len >= buf.length && markpos < 0) {
// XXX - seek, update bufpos - how?
return in.read(b, off, len);
}
}
fill();
avail = count - pos;
if (avail <= 0) return -1;
}
int cnt = (avail < len) ? avail : len;
System.arraycopy(buf, pos, b, off, cnt);
pos += cnt;
return cnt;
| public synchronized void | reset()See the general contract of the reset
method of InputStream .
If markpos is -1
(no mark has been set or the mark has been
invalidated), an IOException
is thrown. Otherwise, pos is
set equal to markpos .
ensureOpen();
if (markpos < 0)
throw new IOException("Resetting to invalid mark");
pos = markpos;
| public synchronized long | skip(long n)See the general contract of the skip
method of InputStream .
ensureOpen();
if (n <= 0) {
return 0;
}
long avail = count - pos;
if (avail <= 0) {
// If no mark position set then don't keep in buffer
/*
if (markpos <0)
return in.skip(n);
*/
// Fill in buffer to save bytes for reset
fill();
avail = count - pos;
if (avail <= 0)
return 0;
}
long skipped = (avail < n) ? avail : n;
pos += skipped;
return skipped;
|
|