FileCacheImageInputStreampublic class FileCacheImageInputStream extends ImageInputStreamImpl An implementation of ImageInputStream that gets its
input from a regular InputStream . A file is used to
cache previously read data. |
Fields Summary |
---|
private InputStream | stream | private File | cacheFile | private RandomAccessFile | cache | private static final int | BUFFER_LENGTH | private byte[] | buf | private long | length | private boolean | foundEOF | private final Object | disposerReferentThe referent to be registered with the Disposer. | private final DisposerRecord | disposerRecordThe DisposerRecord that closes the underlying cache. |
Constructors Summary |
---|
public FileCacheImageInputStream(InputStream stream, File cacheDir)Constructs a FileCacheImageInputStream that will read
from a given InputStream .
A temporary file is used as a cache. If
cacheDir is non-null and is a
directory, the file will be created there. If it is
null , the system-dependent default temporary-file
directory will be used (see the documentation for
File.createTempFile for details).
if (stream == null) {
throw new IllegalArgumentException("stream == null!");
}
if ((cacheDir != null) && !(cacheDir.isDirectory())) {
throw new IllegalArgumentException("Not a directory!");
}
this.stream = stream;
this.cacheFile =
File.createTempFile("imageio", ".tmp", cacheDir);
this.cache = new RandomAccessFile(cacheFile, "rw");
StreamCloser.addToQueue(this);
disposerRecord = new StreamDisposerRecord(cacheFile, cache);
if (getClass() == FileCacheImageInputStream.class) {
disposerReferent = new Object();
Disposer.addRecord(disposerReferent, disposerRecord);
} else {
disposerReferent = new StreamFinalizer(this);
}
|
Methods Summary |
---|
public void | close()Closes this FileCacheImageInputStream , closing
and removing the cache file. The source InputStream
is not closed.
super.close();
disposerRecord.dispose(); // this will close/delete the cache file
stream = null;
cache = null;
cacheFile = null;
StreamCloser.removeFromQueue(this);
| protected void | finalize(){@inheritDoc}
// Empty finalizer: for performance reasons we instead use the
// Disposer mechanism for ensuring that the underlying
// RandomAccessFile is closed/deleted prior to garbage collection
| public boolean | isCached()Returns true since this
ImageInputStream caches data in order to allow
seeking backwards.
return true;
| public boolean | isCachedFile()Returns true since this
ImageInputStream maintains a file cache.
return true;
| public boolean | isCachedMemory()Returns false since this
ImageInputStream does not maintain a main memory
cache.
return false;
| public int | read()
checkClosed();
bitOffset = 0;
long next = streamPos + 1;
long pos = readUntil(next);
if (pos >= next) {
cache.seek(streamPos++);
return cache.read();
} else {
return -1;
}
| public int | read(byte[] b, int off, int len)
checkClosed();
if (b == null) {
throw new NullPointerException("b == null!");
}
// Fix 4430357 - if off + len < 0, overflow occurred
if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
throw new IndexOutOfBoundsException
("off < 0 || len < 0 || off+len > b.length || off+len < 0!");
}
bitOffset = 0;
if (len == 0) {
return 0;
}
long pos = readUntil(streamPos + len);
// len will always fit into an int so this is safe
len = (int)Math.min((long)len, pos - streamPos);
if (len > 0) {
cache.seek(streamPos);
cache.readFully(b, off, len);
streamPos += len;
return len;
} else {
return -1;
}
| private long | readUntil(long pos)Ensures that at least pos bytes are cached,
or the end of the source is reached. The return value
is equal to the smaller of pos and the
length of the source file.
// We've already got enough data cached
if (pos < length) {
return pos;
}
// pos >= length but length isn't getting any bigger, so return it
if (foundEOF) {
return length;
}
long len = pos - length;
cache.seek(length);
while (len > 0) {
// Copy a buffer's worth of data from the source to the cache
// BUFFER_LENGTH will always fit into an int so this is safe
int nbytes =
stream.read(buf, 0, (int)Math.min(len, (long)BUFFER_LENGTH));
if (nbytes == -1) {
foundEOF = true;
return length;
}
cache.write(buf, 0, nbytes);
len -= nbytes;
length += nbytes;
}
return pos;
|
|