jj2000.j2k.io.BufferedRandomAccessFile Maven / Gradle / Ivy
Show all versions of jai-imageio-jpeg2000 Show documentation
/*
* $RCSfile: BufferedRandomAccessFile.java,v $
* $Revision: 1.1 $
* $Date: 2005/02/11 05:02:16 $
* $State: Exp $
*
* Interface: RandomAccessIO.java
*
* Description: Abstract class for buffered random access I/O.
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
*
* Copyright (c) 1999/2000 JJ2000 Partners.
*/
package jj2000.j2k.io;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* This class defines a Buffered Random Access File. It implements the
* BinaryDataInput and BinaryDataOutput interfaces so that
* binary data input/output can be performed. This class is abstract since no
* assumption is done about the byte ordering type (little Endian, big
* Endian). So subclasses will have to implement methods like
* readShort(), writeShort(), readFloat(), ...
*
* BufferedRandomAccessFile (BRAF for short) is a
* RandomAccessFile containing an extra buffer. When the BRAF is
* accessed, it checks if the requested part of the file is in the buffer or
* not. If that is the case, the read/write is done on the buffer. If not, the
* file is uppdated to reflect the current status of the buffer and the file
* is then accessed for a new buffer containing the requested byte/bit.
*
* @see RandomAccessIO
* @see BinaryDataOutput
* @see BinaryDataInput
* @see BEBufferedRandomAccessFile
* */
public abstract class BufferedRandomAccessFile
implements RandomAccessIO, EndianType {
/**
* The name of the current file
* */
private String fileName;
/**
* Whether the opened file is read only or not (defined by the constructor
* arguments)
* */
private boolean isReadOnly = true;
/**
* The RandomAccessFile associated with the buffer
* */
private RandomAccessFile theFile;
/**
* Buffer of bytes containing the part of the file that is currently being
* accessed
* */
protected byte[] byteBuffer;
/**
* Boolean keeping track of whether the byte buffer has been changed since
* it was read.
* */
protected boolean byteBufferChanged;
/**
* The current offset of the buffer (which will differ from the offset of
* the file)
* */
protected int offset;
/**
* The current position in the byte-buffer
* */
protected int pos;
/**
* The maximum number of bytes that can be read from the buffer
* */
protected int maxByte;
/**
* Whether the end of the file is in the current buffer or not
* */
protected boolean isEOFInBuffer;
/* The endianess of the class */
protected int byteOrdering;
/**
* Constructor. Always needs a size for the buffer.
*
* @param file The file associated with the buffer
*
* @param mode "r" for read, "rw" or "rw+" for read and write mode ("rw+"
* opens the file for update whereas "rw" removes it
* before. So the 2 modes are different only if the file
* already exists).
*
* @param bufferSize The number of bytes to buffer
*
* @exception java.io.IOException If an I/O error ocurred.
* */
protected BufferedRandomAccessFile(File file,
String mode,
int bufferSize) throws IOException{
fileName = file.getName();
if(mode.equals("rw") || mode.equals("rw+")){ // mode read / write
isReadOnly = false;
if(mode.equals("rw")){ // mode read / (over)write
if(file.exists()) // Output file already exists
file.delete();
}
mode = "rw";
}
theFile=new RandomAccessFile(file,mode);
byteBuffer=new byte[bufferSize];
readNewBuffer(0);
}
/**
* Constructor. Uses the default value for the byte-buffer
* size (512 bytes).
*
* @param file The file associated with the buffer
*
* @param mode "r" for read, "rw" or "rw+" for read and write mode
* ("rw+" opens the file for update whereas "rw" removes
* it before. So the 2 modes are different only if the
* file already exists).
*
* @exception java.io.IOException If an I/O error ocurred.
* */
protected BufferedRandomAccessFile(File file,
String mode ) throws IOException{
this(file, mode, 512);
}
/**
* Constructor. Always needs a size for the buffer.
*
* @param name The name of the file associated with the buffer
*
* @param mode "r" for read, "rw" or "rw+" for read and write mode
* ("rw+" opens the file for update whereas "rw" removes
* it before. So the 2 modes are different only if the
* file already exists).
*
* @param bufferSize The number of bytes to buffer
*
* @exception java.io.IOException If an I/O error ocurred.
* */
protected BufferedRandomAccessFile(String name,
String mode,
int bufferSize) throws IOException{
this(new File(name), mode, bufferSize);
}
/**
* Constructor. Uses the default value for the byte-buffer
* size (512 bytes).
*
* @param name The name of the file associated with the buffer
*
* @param mode "r" for read, "rw" or "rw+" for read and write mode
* ("rw+" opens the file for update whereas "rw" removes
* it before. So the 2 modes are different only if the
* file already exists).
*
* @exception java.io.IOException If an I/O error ocurred.
* */
protected BufferedRandomAccessFile(String name,
String mode ) throws IOException{
this(name, mode, 512);
}
/**
* Reads a new buffer from the file. If there has been any
* changes made since the buffer was read, the buffer is
* first written to the file.
*
* @param off The offset where to move to.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
protected final void readNewBuffer(int off) throws IOException{
/* If the buffer have changed. We need to write it to
* the file before reading a new buffer.
*/
if(byteBufferChanged){
flush();
}
// Don't allow to seek beyond end of file if reading only
if (isReadOnly && off >= theFile.length()) {
throw new EOFException();
}
// Set new offset
offset = off;
theFile.seek(offset);
maxByte = theFile.read(byteBuffer,0,byteBuffer.length);
pos=0;
if(maxByte=offset)&&(off<(offset+byteBuffer.length)) ){
if (isReadOnly && isEOFInBuffer && off > offset+maxByte) {
// We are seeking beyond EOF in read-only mode!
throw new EOFException();
}
pos = off-offset;
}
else{
readNewBuffer(off);
}
}
/**
* Reads an unsigned byte of data from the stream. Prior to reading, the
* stream is realigned at the byte level.
*
* @return The byte read.
*
* @exception java.io.IOException If an I/O error ocurred.
*
* @exception java.io.EOFException If the end of file was reached
* */
public final int read() throws IOException, EOFException{
if(pos 0) {
// There still is some data to read
if (pos len) clen = len;
System.arraycopy(byteBuffer,pos,b,off,clen);
pos += clen;
off += clen;
len -= clen;
}
else if (isEOFInBuffer) {
pos = maxByte+1; // Set position to EOF
throw new EOFException();
}
else { // Buffer empty => get more data
readNewBuffer(offset+pos);
}
}
}
/**
* Writes a byte to the stream. Prior to writing, the stream is
* realigned at the byte level.
*
* @param b The byte to write. The lower 8 bits of b are
* written.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final void write(int b) throws IOException{
// As long as pos is less than the length of the buffer we can write
// to the buffer. If the position is after the buffer a new buffer is
// needed
if(pos=maxByte){
maxByte=pos+1;
}
pos++;
byteBufferChanged =true;
}
else{
readNewBuffer(offset+pos);
write(b);
}
}
/**
* Writes a byte to the stream. Prior to writing, the stream is
* realigned at the byte level.
*
* @param b The byte to write.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final void write(byte b) throws IOException{
// As long as pos is less than the length of the buffer we can write
// to the buffer. If the position is after the buffer a new buffer is
// needed
if(pos=maxByte){
maxByte=pos+1;
}
pos++;
byteBufferChanged =true;
}
else{
readNewBuffer(offset+pos);
write(b);
}
}
/**
* Writes aan array of bytes to the stream. Prior to writing, the stream is
* realigned at the byte level.
*
* @param b The array of bytes to write.
*
* @param offset The first byte in b to write
*
* @param length The number of bytes from b to write
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final void write(byte[] b, int offset, int length)
throws IOException{
int i,stop;
stop = offset+length;
if(stop > b.length)
throw new ArrayIndexOutOfBoundsException(b.length);
for(i=offset ; iv (i.e., 8 least
* significant bits) to the output. Prior to writing, the output
* should be realigned at the byte level.
*
* Signed or unsigned data can be written. To write a signed
* value just pass the byte value as an argument. To
* write unsigned data pass the int value as an argument
* (it will be automatically casted, and only the 8 least
* significant bits will be written).
*
* @param v The value to write to the output
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final void writeByte(int v) throws IOException{
write(v);
}
/**
* Any data that has been buffered must be written (including
* buffering at the bit level), and the stream should be realigned
* at the byte level.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final void flush() throws IOException{
if(byteBufferChanged){
theFile.seek(offset);
theFile.write(byteBuffer,0,maxByte);
byteBufferChanged = false;
}
}
/**
* Reads a signed byte (i.e., 8 bit) from the input. Prior to
* reading, the input should be realigned at the byte level.
*
* @return The next byte-aligned signed byte (8 bit) from the
* input.
*
* @exception java.io.EOFException If the end-of file was reached before
* getting all the necessary data.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final byte readByte() throws EOFException, IOException {
if(posint since Java does not have an
* unsigned byte type. Prior to reading, the input should be
* realigned at the byte level.
*
* @return The next byte-aligned unsigned byte (8 bit) from the
* input, as an int.
*
* @exception java.io.EOFException If the end-of file was reached before
* getting all the necessary data.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public final int readUnsignedByte() throws EOFException, IOException{
return read();
}
/**
* Returns the endianess (i.e., byte ordering) of the implementing
* class. Note that an implementing class may implement only one
* type of endianness or both, which would be decided at creation
* time.
*
* @return Either EndianType.BIG_ENDIAN or
* EndianType.LITTLE_ENDIAN
*
* @see EndianType
* */
public int getByteOrdering(){
return byteOrdering;
}
/**
* Skips n bytes from the input. Prior to skipping, the
* input should be realigned at the byte level.
*
* @param n The number of bytes to skip
*
* @exception java.io.EOFException If the end-of file was reached before
* all the bytes could be skipped.
*
* @exception java.io.IOException If an I/O error ocurred.
* */
public int skipBytes(int n)throws EOFException, IOException{
if(n<0)
throw new IllegalArgumentException("Can not skip negative number "+
"of bytes");
if(n <= (maxByte-pos)){
pos += n;
return n;
}
else{
seek(offset+pos+n);
return n;
}
}
/**
* Returns a string of information about the file
* */
public String toString(){
return "BufferedRandomAccessFile: "+fileName+" ("+
((isReadOnly)?"read only":"read/write")+
")";
}
}