org.eclipse.mat.parser.io.BufferedRandomAccessInputStream Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2008 SAP AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.mat.parser.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.lang.ref.SoftReference;
import org.eclipse.mat.collect.HashMapLongObject;
public class BufferedRandomAccessInputStream extends InputStream {
RandomAccessFile raf;
private class Page {
long real_pos_start;
byte[] buffer;
int buf_end;
public Page() {
buffer = new byte[bufsize];
}
}
int bufsize;
long fileLength;
long real_pos;
long reported_pos;
HashMapLongObject> pages = new HashMapLongObject>();
Page current;
public BufferedRandomAccessInputStream(RandomAccessFile in) throws IOException {
this(in, 1024);
}
public BufferedRandomAccessInputStream(RandomAccessFile in, int bufsize) throws IOException {
this.bufsize = bufsize;
this.raf = in;
this.fileLength = in.length();
}
public final int read() throws IOException {
if (reported_pos == fileLength)
return -1;
if (current == null || (reported_pos - current.real_pos_start) >= current.buf_end)
current = getPage(reported_pos);
return current.buffer[((int) (reported_pos++ - current.real_pos_start))] & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (reported_pos == fileLength)
return -1;
int copied = 0;
while (copied < len) {
if (reported_pos == fileLength)
return copied;
if (current == null || (reported_pos - current.real_pos_start) >= current.buf_end)
current = getPage(reported_pos);
int buf_pos = (int) (reported_pos - current.real_pos_start);
int length = Math.min(len - copied, current.buf_end - buf_pos);
System.arraycopy(current.buffer, buf_pos, b, off + copied, length);
reported_pos += length;
copied += length;
}
return copied;
}
private Page getPage(long pos) throws IOException {
long key = pos / bufsize;
SoftReference r = pages.get(key);
Page p = r == null ? null : r.get();
if (p != null)
return p;
long page_start = key * bufsize;
if (page_start != real_pos) {
raf.seek(page_start);
real_pos = page_start;
}
p = new Page();
int n = raf.read(p.buffer);
if (n >= 0) {
p.real_pos_start = real_pos;
p.buf_end = n;
real_pos += n;
}
pages.put(key, new SoftReference(p));
return p;
}
public boolean markSupported() {
return false;
}
public void close() throws IOException {
raf.close();
}
/**
* @throws IOException
*/
public void seek(long pos) throws IOException {
reported_pos = pos;
current = null;
}
public long getFilePointer() {
return reported_pos;
}
}