blob: db0abec13eccaf0a410b16fde5f1bbb8c266c749 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.registry;
import java.io.*;
/**
* Provides buffered read from a java.io.RandomAccessFile.
*/
public class BufferedRandomInputStream extends InputStream {
private RandomAccessFile inputFile;
private String filePath; // Canonical path to the underlying file used for logging
private int buffer_size; // Current size of the buffer
private int buffer_pos; // Current read position in the buffer
/**
* The absolute position in the file where the buffered region starts.
*/
private long buffer_start = 0;
/**
* The current value of the RAF's file pointer.
*/
private long file_pointer;
private byte buffer[];
public BufferedRandomInputStream(File file) throws IOException {
this(file, 2048); // default buffer size
}
public BufferedRandomInputStream(File file, int bufferSize) throws IOException {
filePath = file.getCanonicalPath();
inputFile = new RandomAccessFile(file, "r"); //$NON-NLS-1$
buffer = new byte[bufferSize];
file_pointer = 0;
resetBuffer();
}
private void resetBuffer() {
buffer_pos = 0;
buffer_size = 0;
buffer_start = 0;
}
private int fillBuffer() throws IOException {
buffer_pos = 0;
buffer_start = file_pointer;
buffer_size = inputFile.read(buffer, 0, buffer.length);
file_pointer += buffer_size;
return buffer_size;
}
public int read() throws IOException {
if (buffer_pos >= buffer_size) {
if (fillBuffer() <= 0)
return -1;
}
return buffer[buffer_pos++] & 0xFF;
}
public int read(byte b[], int off, int len) throws IOException {
int available = buffer_size - buffer_pos;
if (available < 0)
return -1;
//the buffer contains all the bytes we need, so copy over and return
if (len <= available) {
System.arraycopy(buffer, buffer_pos, b, off, len);
buffer_pos += len;
return len;
}
// Use portion remaining in the buffer
System.arraycopy(buffer, buffer_pos, b, off, available);
if (fillBuffer() <= 0)
return available;
//recursive call to read again until we have the bytes we need
return available + read(b, off + available, len - available);
}
public long skip(long n) throws IOException {
if (n <= 0)
return 0;
int available = buffer_size - buffer_pos;
if (n <= available) {
buffer_pos += n;
return n;
}
resetBuffer();
final int skipped = inputFile.skipBytes((int) (n - available));
file_pointer += skipped;
return available + skipped;
}
public int available() throws IOException {
return (buffer_size - buffer_pos);
}
public void close() throws IOException {
inputFile.close();
inputFile = null;
buffer = null;
}
public String toString() {
return filePath;
}
/**
* Supplies functionality of the {@link java.io.RandomAccessFile#seek(long)} in
* a buffer-friendly manner.
*
* @param pos offset
* @throws IOException
*/
public void seek(long pos) throws IOException {
if (pos >= buffer_start && pos < buffer_start + buffer_size) {
//seeking within the current buffer
buffer_pos = (int) (pos - buffer_start);
} else {
//seeking outside the buffer - just discard the buffer
inputFile.seek(pos);
file_pointer = pos;
resetBuffer();
}
}
/**
* Supplies functionality of the {@link java.io.RandomAccessFile#length()}.
* @return file length
* @throws IOException
*/
public long length() throws IOException {
return inputFile.length();
}
}