2009-09-30 23:50:03 +00:00
/ *
* CVS Identifier :
*
* $ Id : BufferedRandomAccessFile . java , v 1.21 2001 / 04 / 15 14 : 34 : 29 grosbois Exp $
*
* Interface : RandomAccessIO . java
*
* Description : Abstract class for buffered random access I / O .
*
*
*
* COPYRIGHT :
*
* This software module was originally developed by Rapha <EFBFBD> l Grosbois and
* Diego Santa Cruz ( Swiss Federal Institute of Technology - EPFL ) ; Joel
* Askel <EFBFBD> f ( Ericsson Radio Systems AB ) ; and Bertrand Berthelot , David
* Bouchard , F <EFBFBD> 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 .
* * /
using System ;
namespace CSJ2K.j2k.io
{
/// <summary> This class defines a Buffered Random Access File. It implements the
/// <tt>BinaryDataInput</tt> and <tt>BinaryDataOutput</tt> 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
/// <tt>readShort()</tt>, <tt>writeShort()</tt>, <tt>readFloat()</tt>, ...
///
/// <P><tt>BufferedRandomAccessFile</tt> (BRAF for short) is a
/// <tt>RandomAccessFile</tt> 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.
///
/// </summary>
/// <seealso cref="RandomAccessIO">
/// </seealso>
/// <seealso cref="BinaryDataOutput">
/// </seealso>
/// <seealso cref="BinaryDataInput">
/// </seealso>
/// <seealso cref="BEBufferedRandomAccessFile">
///
/// </seealso>
public abstract class BufferedRandomAccessFile : RandomAccessIO , EndianType
{
/// <summary> Returns the current offset in the file
///
/// </summary>
virtual public int Pos
{
get
{
return ( offset + position ) ;
}
}
/// <summary> 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.
///
/// </summary>
/// <returns> Either <tt>EndianType.BIG_ENDIAN</tt> or
/// <tt>EndianType.LITTLE_ENDIAN</tt>
///
/// </returns>
/// <seealso cref="EndianType">
///
/// </seealso>
virtual public int ByteOrdering
{
get
{
return byte_Ordering ;
}
}
/// <summary>The name of the current file </summary>
private System . String fileName ;
/// <summary> Whether the opened file is read only or not (defined by the constructor
/// arguments)
///
/// </summary>
private bool isReadOnly = true ;
/// <summary> The RandomAccessFile associated with the buffer
///
/// </summary>
//UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'"
private System . IO . FileStream theFile ;
/// <summary> Buffer of bytes containing the part of the file that is currently being
/// accessed
///
/// </summary>
protected internal byte [ ] byteBuffer ;
/// <summary> Boolean keeping track of whether the byte buffer has been changed since
/// it was read.
///
/// </summary>
protected internal bool byteBufferChanged ;
/// <summary> The current offset of the buffer (which will differ from the offset of
/// the file)
///
/// </summary>
protected internal int offset ;
/// <summary> The current position in the byte-buffer
///
/// </summary>
protected internal int position ;
/// <summary> The maximum number of bytes that can be read from the buffer
///
/// </summary>
protected internal int maxByte ;
/// <summary> Whether the end of the file is in the current buffer or not
///
/// </summary>
protected internal bool isEOFInBuffer ;
/* The endianess of the class */
protected internal int byte_Ordering ;
/// <summary> Constructor. Always needs a size for the buffer.
///
/// </summary>
/// <param name="file">The file associated with the buffer
///
/// </param>
/// <param name="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>
/// <param name="bufferSize">The number of bytes to buffer
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
protected internal BufferedRandomAccessFile ( System . IO . FileInfo file , System . String mode , int bufferSize )
{
fileName = file . Name ;
if ( mode . Equals ( "rw" ) | | mode . Equals ( "rw+" ) )
{
// mode read / write
isReadOnly = false ;
if ( mode . Equals ( "rw" ) )
{
// mode read / (over)write
bool tmpBool ;
if ( System . IO . File . Exists ( file . FullName ) )
tmpBool = true ;
else
tmpBool = System . IO . Directory . Exists ( file . FullName ) ;
if ( tmpBool )
// Output file already exists
{
bool tmpBool2 ;
if ( System . IO . File . Exists ( file . FullName ) )
{
System . IO . File . Delete ( file . FullName ) ;
tmpBool2 = true ;
}
else if ( System . IO . Directory . Exists ( file . FullName ) )
{
System . IO . Directory . Delete ( file . FullName ) ;
tmpBool2 = true ;
}
else
tmpBool2 = false ;
bool generatedAux = tmpBool2 ;
}
}
mode = "rw" ;
}
theFile = SupportClass . RandomAccessFileSupport . CreateRandomAccessFile ( file , mode ) ;
byteBuffer = new byte [ bufferSize ] ;
readNewBuffer ( 0 ) ;
}
/// <summary> Constructor. Uses the default value for the byte-buffer
/// size (512 bytes).
///
/// </summary>
/// <param name="file">The file associated with the buffer
///
/// </param>
/// <param name="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>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
protected internal BufferedRandomAccessFile ( System . IO . FileInfo file , System . String mode ) : this ( file , mode , 512 )
{
}
/// <summary> Constructor. Always needs a size for the buffer.
///
/// </summary>
/// <param name="name">The name of the file associated with the buffer
///
/// </param>
/// <param name="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>
/// <param name="bufferSize">The number of bytes to buffer
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
protected internal BufferedRandomAccessFile ( System . String name , System . String mode , int bufferSize ) : this ( new System . IO . FileInfo ( name ) , mode , bufferSize )
{
}
/// <summary> Constructor. Uses the default value for the byte-buffer
/// size (512 bytes).
///
/// </summary>
/// <param name="name">The name of the file associated with the buffer
///
/// </param>
/// <param name="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>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
protected internal BufferedRandomAccessFile ( System . String name , System . String mode ) : this ( name , mode , 512 )
{
}
/// <summary> 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.
///
/// </summary>
/// <param name="off">The offset where to move to.
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
protected internal void readNewBuffer ( int off )
{
/ * 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 System . IO . EndOfStreamException ( ) ;
}
// Set new offset
offset = off ;
theFile . Seek ( offset , System . IO . SeekOrigin . Begin ) ;
maxByte = theFile . Read ( byteBuffer , 0 , byteBuffer . Length ) ;
position = 0 ;
if ( maxByte < byteBuffer . Length )
{
// Not enough data in input file.
isEOFInBuffer = true ;
if ( maxByte = = - 1 )
{
maxByte + + ;
}
}
else
{
isEOFInBuffer = false ;
}
}
/// <summary> Closes the buffered random access file
///
/// </summary>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public virtual void close ( )
{
/ * If the buffer has been changed , it need to be saved before
* closing
* /
flush ( ) ;
byteBuffer = null ; // Release the byte-buffer reference
theFile . Close ( ) ;
}
/// <summary> Returns the current length of the stream, in bytes, taking into
/// account any buffering.
///
/// </summary>
/// <returns> The length of the stream, in bytes.
///
/// </returns>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public virtual int length ( )
{
int len ;
len = ( int ) theFile . Length ;
// If the position in the buffer is not past the end of the file,
// the length of theFile is the length of the stream
if ( ( offset + maxByte ) < = len )
{
return ( len ) ;
}
else
{
// If not, the file is extended due to the buffering
return ( offset + maxByte ) ;
}
}
/// <summary> Moves the current position to the given offset at which the
/// next read or write occurs. The offset is measured from the
/// beginning of the stream.
///
/// </summary>
/// <param name="off">The offset where to move to.
///
/// </param>
/// <exception cref="EOFException">If in read-only and seeking beyond EOF.
///
/// </exception>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public virtual void seek ( int off )
{
/ * If the new offset is within the buffer , only the pos value needs
* to be modified . Else , the buffer must be moved . * /
if ( ( off > = offset ) & & ( off < ( offset + byteBuffer . Length ) ) )
{
if ( isReadOnly & & isEOFInBuffer & & off > offset + maxByte )
{
// We are seeking beyond EOF in read-only mode!
throw new System . IO . EndOfStreamException ( ) ;
}
position = off - offset ;
}
else
{
readNewBuffer ( off ) ;
}
}
/// <summary> Reads an unsigned byte of data from the stream. Prior to reading, the
/// stream is realigned at the byte level.
///
/// </summary>
/// <returns> The byte read.
///
/// </returns>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
/// <exception cref="java.io.EOFException">If the end of file was reached
///
/// </exception>
public byte readByte ( ) { return read ( ) ; }
public byte readUnsignedByte ( ) { return read ( ) ; }
public byte read ( )
{
if ( position < maxByte )
{
// The byte can be read from the buffer
// In Java, the bytes are always signed.
return ( byteBuffer [ position + + ] ) ;
}
else if ( isEOFInBuffer )
{
// EOF is reached
position = maxByte + 1 ; // Set position to EOF
throw new System . IO . EndOfStreamException ( ) ;
}
else
{
// End of the buffer is reached
readNewBuffer ( offset + position ) ;
return read ( ) ;
}
}
/// <summary> Reads up to len bytes of data from this file into an array of
/// bytes. This method reads repeatedly from the stream until all the bytes
/// are read. This method blocks until all the bytes are read, the end of
/// the stream is detected, or an exception is thrown.
///
/// </summary>
/// <param name="b">The buffer into which the data is to be read. It must be long
/// enough.
///
/// </param>
/// <param name="off">The index in 'b' where to place the first byte read.
///
/// </param>
/// <param name="len">The number of bytes to read.
///
/// </param>
/// <exception cref="EOFException">If the end-of file was reached before
/// getting all the necessary data.
///
/// </exception>
/// <exception cref="IOException">If an I/O error ocurred.
///
/// </exception>
public void readFully ( byte [ ] b , int off , int len )
{
int clen ; // current length to read
while ( len > 0 )
{
// There still is some data to read
if ( position < maxByte )
{
// We can read some data from buffer
clen = maxByte - position ;
if ( clen > len )
clen = len ;
2010-08-06 03:11:08 +00:00
Array . Copy ( byteBuffer , position , b , off , clen ) ;
2009-09-30 23:50:03 +00:00
position + = clen ;
off + = clen ;
len - = clen ;
}
else if ( isEOFInBuffer )
{
position = maxByte + 1 ; // Set position to EOF
throw new System . IO . EndOfStreamException ( ) ;
}
else
{
// Buffer empty => get more data
readNewBuffer ( offset + position ) ;
}
}
}
/// <summary> Writes a byte to the stream. Prior to writing, the stream is
/// realigned at the byte level.
///
/// </summary>
/// <param name="b">The byte to write. The lower 8 bits of <tt>b</tt> are
/// written.
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public void write ( int b )
{
// 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 ( position < byteBuffer . Length )
{
if ( isReadOnly )
throw new System . IO . IOException ( "File is read only" ) ;
byteBuffer [ position ] = ( byte ) b ;
if ( position > = maxByte )
{
maxByte = position + 1 ;
}
position + + ;
byteBufferChanged = true ;
}
else
{
readNewBuffer ( offset + position ) ;
write ( b ) ;
}
}
/// <summary> Writes a byte to the stream. Prior to writing, the stream is
/// realigned at the byte level.
///
/// </summary>
/// <param name="b">The byte to write.
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public void write ( byte b )
{
// 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 ( position < byteBuffer . Length )
{
if ( isReadOnly )
throw new System . IO . IOException ( "File is read only" ) ;
byteBuffer [ position ] = b ;
if ( position > = maxByte )
{
maxByte = position + 1 ;
}
position + + ;
byteBufferChanged = true ;
}
else
{
readNewBuffer ( offset + position ) ;
write ( b ) ;
}
}
/// <summary> Writes aan array of bytes to the stream. Prior to writing, the stream is
/// realigned at the byte level.
///
/// </summary>
/// <param name="b">The array of bytes to write.
///
/// </param>
/// <param name="offset">The first byte in b to write
///
/// </param>
/// <param name="length">The number of bytes from b to write
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public void write ( byte [ ] b , int offset , int length )
{
int i , stop ;
stop = offset + length ;
if ( stop > b . Length )
throw new System . IndexOutOfRangeException ( "Index of bound " + b . Length ) ;
for ( i = offset ; i < stop ; i + + )
{
write ( b [ i ] ) ;
}
}
/// <summary> Writes the byte value of <tt>v</tt> (i.e., 8 least
/// significant bits) to the output. Prior to writing, the output
/// should be realigned at the byte level.
///
/// <P>Signed or unsigned data can be written. To write a signed
/// value just pass the <tt>byte</tt> value as an argument. To
/// write unsigned data pass the <tt>int</tt> value as an argument
/// (it will be automatically casted, and only the 8 least
/// significant bits will be written).
///
/// </summary>
/// <param name="v">The value to write to the output
///
/// </param>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public void writeByte ( int v )
{
write ( v ) ;
}
/// <summary> 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.
///
/// </summary>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public void flush ( )
{
if ( byteBufferChanged )
{
theFile . Seek ( offset , System . IO . SeekOrigin . Begin ) ;
theFile . Write ( byteBuffer , 0 , maxByte ) ;
byteBufferChanged = false ;
}
}
/ *
/// <summary> Reads a signed byte (i.e., 8 bit) from the input. Prior to
/// reading, the input should be realigned at the byte level.
///
/// </summary>
/// <returns> The next byte-aligned signed byte (8 bit) from the
/// input.
///
/// </returns>
/// <exception cref="java.io.EOFException">If the end-of file was reached before
/// getting all the necessary data.
///
/// </exception>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public byte readByte ( )
{
if ( pos < maxByte )
{
// The byte can be read from the buffer
// In Java, the bytes are always signed.
return byteBuffer [ pos + + ] ;
}
else if ( isEOFInBuffer )
{
// EOF is reached
pos = maxByte + 1 ; // Set position to EOF
throw new System . IO . EndOfStreamException ( ) ;
}
else
{
// End of the buffer is reached
readNewBuffer ( offset + pos ) ;
return readByte ( ) ;
}
}
/// <summary> Reads an unsigned byte (i.e., 8 bit) from the input. It is
/// returned as an <tt>int</tt> since Java does not have an
/// unsigned byte type. Prior to reading, the input should be
/// realigned at the byte level.
///
/// </summary>
/// <returns> The next byte-aligned unsigned byte (8 bit) from the
/// input, as an <tt>int</tt>.
///
/// </returns>
/// <exception cref="java.io.EOFException">If the end-of file was reached before
/// getting all the necessary data.
///
/// </exception>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public int readUnsignedByte ( )
{
return read ( ) ;
}
* /
/// <summary> Skips <tt>n</tt> bytes from the input. Prior to skipping, the
/// input should be realigned at the byte level.
///
/// </summary>
/// <param name="n">The number of bytes to skip
///
/// </param>
/// <exception cref="java.io.EOFException">If the end-of file was reached before
/// all the bytes could be skipped.
///
/// </exception>
/// <exception cref="java.io.IOException">If an I/O error ocurred.
///
/// </exception>
public virtual int skipBytes ( int n )
{
if ( n < 0 )
throw new System . ArgumentException ( "Can not skip negative number " + "of bytes" ) ;
if ( n < = ( maxByte - position ) )
{
position + = n ;
return n ;
}
else
{
seek ( offset + position + n ) ;
return n ;
}
}
/// <summary> Returns a string of information about the file
///
/// </summary>
public override System . String ToString ( )
{
return "BufferedRandomAccessFile: " + fileName + " (" + ( ( isReadOnly ) ? "read only" : "read/write" ) + ")" ;
}
public abstract int readUnsignedShort ( ) ;
public abstract void writeLong ( long param1 ) ;
public abstract void writeShort ( int param1 ) ;
public abstract float readFloat ( ) ;
public abstract short readShort ( ) ;
public abstract double readDouble ( ) ;
public abstract int readInt ( ) ;
public abstract long readLong ( ) ;
public abstract long readUnsignedInt ( ) ;
public abstract void writeDouble ( double param1 ) ;
public abstract void writeFloat ( float param1 ) ;
public abstract void writeInt ( int param1 ) ;
}
}