package com.isti.traceview.data;
//$Id: RandomAccessFile.java 64 2006-07-12 22:30:50Z edavis $
/*
* Copyright 1997-2006 Unidata Program Center/University Corporation for
* Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
* support@unidata.ucar.edu.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
/**
* By Russ Rew, based on RandomAccessFile by Alex McManus, based on Sun's
* source code for java.io.RandomAccessFile. For Alex McManus version from which this derives, see
* his <a href="http://www.aber.ac.uk/~agm/Java.html"> Freeware Java Classes</a>. A buffered
* drop-in replacement for java.io.RandomAccessFile. Instances of this class realise substantial
* speed increases over java.io.RandomAccessFile through the use of buffering. This is a subclass of
* Object, as it was not possible to subclass java.io.RandomAccessFile because many of the methods
* are final. However, if it is necessary to use RandomAccessFile and java.io.RandomAccessFile
* interchangeably, both classes implement the DataInput and DataOutput interfaces.
*
* @author Alex McManus
* @author Russ Rew
* @author john caron
* @see DataInput
* @see DataOutput
* @see java.io.RandomAccessFile
*/
public class BufferedRandomAccessFile implements DataInput, DataOutput {
/** _more_. */
static public final int BIG_ENDIAN = 0;
/** _more_. */
static public final int LITTLE_ENDIAN = 1;
// debug leaks - keep track of open files
/**
* Debugging, do not use.
*
* @param b the new debug leaks
*/
static public void setDebugLeaks(boolean b) {
debugLeaks = b;
}
/**
* Debugging, do not use.
*
* @param b the new debug access
*/
static public void setDebugAccess(boolean b) {
debugAccess = b;
}
/** _more_. */
static protected boolean debugLeaks = false;
/** The debug access. */
static protected boolean debugAccess = false;
/** _more_. */
static public List<String> openFiles = Collections.synchronizedList(new ArrayList<String>());
/** The default buffer size, in bytes. */
protected static final int defaultBufferSize = 8092; // LOOK time this
/** _more_. */
protected String location;
/** The underlying java.io.RandomAccessFile. */
protected java.io.RandomAccessFile file;
/**
* The offset in bytes from the file start, of the next read or write operation.
*/
protected long filePosition;
/** The buffer used to load the data. */
protected byte buffer[];
/**
* The offset in bytes of the start of the buffer, from the start of the file.
*/
protected long bufferStart;
/**
* The offset in bytes of the end of the data in the buffer, from the start of the file. This
* can be calculated from <code>bufferStart + dataSize</code>, but it is cached to speed up
* the read( ) method.
*/
protected long dataEnd;
/**
* The size of the data stored in the buffer, in bytes. This may be less than the size of the
* buffer.
*/
protected int dataSize;
/** True if we are at the end of the file. */
protected boolean endOfFile;
/** The access mode of the file. */
protected boolean readonly;
/** The current endian (big or little) mode of the file. */
protected boolean bigEndian;
/** True if the data in the buffer has been modified. */
boolean bufferModified = false;
/** make sure file is this long when closed. */
private long minLength = 0;
/** stupid extendMode for truncated, yet valid files - old code allowed NOFILL to do this. */
boolean extendMode = false;
// for HTTPRandomAccessFile
/**
* _more_.
*
* @param bufferSize _more_
*/
protected BufferedRandomAccessFile(int bufferSize) {
file = null;
readonly = true;
init(bufferSize);
}
/**
* Constructor, default buffer size.
*
* @param location
* location of the file
* @param mode
* same as for java.io.RandomAccessFile
* @throws IOException if there is an issue opening the file
*/
public BufferedRandomAccessFile(String location, String mode) throws IOException {
this(location, mode, defaultBufferSize);
this.location = location;
}
/**
* Constructor.
*
* @param location
* location of the file
* @param mode
* same as for java.io.RandomAccessFile
* @param bufferSize
* size of buffer to use.
* @throws IOException if there is an issue opening the file
*/
public BufferedRandomAccessFile(String location, String mode, int bufferSize)
throws IOException {
this.location = location;
this.file = new java.io.RandomAccessFile(location, mode);
this.readonly = mode.equals("r");
init(bufferSize);
if (debugLeaks) {
openFiles.add(location);
}
}
/**
* Allow access to the underlying java.io.RandomAccessFile. WARNING! BROKEN ENCAPSOLATION, DO
* NOT USE. May change implementation in the future.
*
* @return the underlying java.io.RandomAccessFile.
*/
public java.io.RandomAccessFile getRandomAccessFile() {
return this.file;
}
/**
* _more_.
*
* @param bufferSize _more_
*/
private void init(int bufferSize) {
// Initialise the buffer
bufferStart = 0;
dataEnd = 0;
dataSize = 0;
filePosition = 0;
buffer = new byte[bufferSize];
endOfFile = false;
}
/**
* Close the file, and release any associated system resources.
*
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized void close() throws IOException {
if (debugLeaks) {
openFiles.remove(location);
}
if (file == null) {
return;
}
// If we are writing and the buffer has been modified, flush the contents
// of the buffer.
if (!readonly && bufferModified) {
file.seek(bufferStart);
file.write(buffer, 0, dataSize);
}
/*
* may need to extend file to minLength if (!readonly && minLength > file.length()) {
* file.seek( minLength-1); file.writeByte(0); }
*/
// may need to extend file, in case no fill is neing used
// may need to truncate file in case overwriting a longer file
// use only if minLength is set (by N3iosp)
if (!readonly && (minLength != 0) && (minLength != file.length())) {
file.setLength(minLength);
}
// Close the underlying file object.
file.close();
file = null; // help the gc
}
/**
* Return true if file pointer is at end of file.
*
* @return _more_
*/
public boolean isAtEndOfFile() {
return endOfFile;
}
/*
* Create channel from file public FileChannel getChannel() { if (file == null) { return null; }
* try { file.seek(0); } catch (IOException e) { e.printStackTrace(); } return
* file.getChannel(); }
*/
/**
* Set the position in the file for the next read or write.
*
* @param pos
* the offset (in bytes) from the start of the file.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized void seek(long pos) throws IOException {
// If the seek is into the buffer, just update the file pointer.
if ((pos >= bufferStart) && (pos < dataEnd)) {
filePosition = pos;
return;
}
// If the current buffer is modified, write it to disk.
if (bufferModified) {
flush();
}
// need new buffer
bufferStart = pos;
filePosition = pos;
dataSize = read_(pos, buffer, 0, buffer.length);
if (dataSize <= 0) {
dataSize = 0;
endOfFile = true;
} else {
endOfFile = false;
}
// Cache the position of the buffer end.
dataEnd = bufferStart + dataSize;
}
/**
* Returns the current position in the file, where the next read or write will occur.
*
* @return the offset from the start of the file in bytes.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized long getFilePointer() throws IOException {
return filePosition;
}
/**
* Get the file location, or name.
*
* @return _more_
*/
public synchronized String getLocation() {
return location;
}
/**
* Get the length of the file. The data in the buffer (which may not have been written the disk
* yet) is taken into account.
*
* @return the length of the file in bytes.
* @exception IOException
* if an I/O error occurrs.
*/
public long length() throws IOException {
long fileLength = file.length();
if (fileLength < dataEnd) {
return dataEnd;
} else {
return fileLength;
}
}
/**
* Change the current endian mode. Subsequent reads of short, int, float, double, long, char
* will use this. Does not currently affect writes. Default values is BIG_ENDIAN.
*
* @param endian
* BIG_ENDIAN or LITTLE_ENDIAN
*/
public void order(int endian) {
this.bigEndian = (endian == BIG_ENDIAN);
}
/**
* Checks if is be.
*
* @return true, if is be
*/
public boolean isBE() {
return bigEndian;
}
/**
* Returns the opaque file descriptor object associated with this file.
*
* @return the file descriptor object associated with this file.
* @exception IOException
* if an I/O error occurs.
*/
public FileDescriptor getFD() throws IOException {
return (file == null) ? null : file.getFD();
}
/**
* Copy the contents of the buffer to the disk.
*
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized void flush() throws IOException {
if (bufferModified) {
file.seek(bufferStart);
file.write(buffer, 0, dataSize);
bufferModified = false;
}
// debug
// FileChannel fc = file.getChannel();
}
/**
* Make sure file is at least this long when its closed. needed when not using fill mode, and
* not all data is written.
*
* @param minLength
* minimum length of the file.
*/
public void setMinLength(long minLength) {
this.minLength = minLength;
}
/**
* Set extendMode for truncated, yet valid files - old NetCDF code allowed this when NOFILL on,
* and user doesnt write all variables.
*/
public void setExtendMode() {
this.extendMode = true;
}
// ////////////////////////////////////////////////////////////////////////////////////////////
// Read primitives.
//
/**
* Read a byte of data from the file, blocking until data is available.
*
* @return the next byte of data, or -1 if the end of the file is reached.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized int read() throws IOException {
// If the file position is within the data, return the byte...
if (filePosition < dataEnd) {
int pos = (int) (filePosition - bufferStart);
filePosition++;
return (buffer[pos] & 0xff);
// ...or should we indicate EOF...
} else if (endOfFile) {
return -1;
// ...or seek to fill the buffer, and try again.
} else {
seek(filePosition);
return read();
}
}
/**
* Read up to <code>len</code> bytes into an array, at a specified offset. This will block
* until at least one byte has been read.
*
* @param b
* the byte array to receive the bytes.
* @param off
* the offset in the array where copying will start.
* @param len
* the number of bytes to copy.
* @return the actual number of bytes read, or -1 if there is not more data due to the end of
* the file being reached.
* @exception IOException
* if an I/O error occurrs.
*/
protected int readBytes(byte b[], int off, int len) throws IOException {
// Check for end of file.
if (endOfFile) {
return -1;
}
// See how many bytes are available in the buffer - if none,
// seek to the file position to update the buffer and try again.
int bytesAvailable = (int) (dataEnd - filePosition);
if (bytesAvailable < 1) {
seek(filePosition);
return readBytes(b, off, len);
}
// Copy as much as we can.
int copyLength = (bytesAvailable >= len) ? len : bytesAvailable;
System.arraycopy(buffer, (int) (filePosition - bufferStart), b, off,
copyLength);
filePosition += copyLength;
// If there is more to copy...
if (copyLength < len) {
int extraCopy = len - copyLength;
// If the amount remaining is more than a buffer's length, read it
// directly from the file.
if (extraCopy > buffer.length) {
extraCopy = read_(filePosition, b, off + copyLength,
len - copyLength);
// ...or read a new buffer full, and copy as much as possible...
} else {
seek(filePosition);
if (!endOfFile) {
extraCopy = (extraCopy > dataSize) ? dataSize : extraCopy;
System.arraycopy(buffer, 0, b, off + copyLength,
extraCopy);
} else {
extraCopy = -1;
}
}
// If we did manage to copy any more, update the file position and
// return the amount copied.
if (extraCopy > 0) {
filePosition += extraCopy;
return copyLength + extraCopy;
}
}
// Return the amount copied.
return copyLength;
}
/**
* read directly, without going through the buffer.
*
* @param pos _more_
* @param b _more_
* @param offset _more_
* @param len _more_
* @return _more_
* @throws IOException _more_
*/
protected int read_(long pos, byte[] b, int offset, int len)
throws IOException {
file.seek(pos);
int n = file.read(b, offset, len);
if (debugAccess)
System.out.println(" read_ " + location + " = " + len + " bytes at " + pos + "; block = " + (pos / buffer.length));
if (extendMode && (n < len)) {
n = len;
}
return n;
}
/**
* Read up to <code>len</code> bytes into an array, at a specified offset. This will block
* until at least one byte has been read.
*
* @param b
* the byte array to receive the bytes.
* @param off
* the offset in the array where copying will start.
* @param len
* the number of bytes to copy.
* @return the actual number of bytes read, or -1 if there is not more data due to the end of
* the file being reached.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
/**
* Read up to <code>b.length( )</code> bytes into an array. This will block until at least one
* byte has been read.
*
* @param b
* the byte array to receive the bytes.
* @return the actual number of bytes read, or -1 if there is not more data due to the end of
* the file being reached.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
/**
* Reads <code>b.length</code> bytes from this file into the byte array. This method reads
* repeatedly from the file 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.
*
* @param b the buffer into which the data is read.
* @exception IOException if an I/O error occurs.
*/
public final void readFully(byte b[]) throws IOException {
readFully(b, 0, b.length);
}
/**
* Reads exactly <code>len</code> bytes from this file into the byte array. This method reads
* repeatedly from the file 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.
*
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the number of bytes to read.
* @exception IOException if an I/O error occurs.
*/
public synchronized final void readFully(byte b[], int off, int len)
throws IOException {
int n = 0;
while (n < len) {
int count = this.read(b, off + n, len - n);
if (count < 0) {
String message = "REACHED MSEED EOF!!!";
throw new EOFException(message);
}
n += count;
}
}
/**
* Skips exactly <code>n</code> bytes of input. This method blocks until all the bytes are
* skipped, the end of the stream is detected, or an exception is thrown.
*
* @param n the number of bytes to be skipped.
* @return the number of bytes skipped, which is always <code>n</code>.
* @exception IOException if an I/O error occurs.
*/
public synchronized int skipBytes(int n) throws IOException {
seek(getFilePointer() + n);
return n;
}
/*
* public void skipToMultiple( int multipleOfBytes) throws IOException { long pos =
* getFilePointer(); int pad = (int) (pos % multipleOfBytes); if (pad != 0) pad =
* multipleOfBytes - pad; if (pad > 0) skipBytes(pad); }
*/
/**
* Unread the last byte read. This method should not be used more than once between reading
* operations, or strange things might happen.
*/
public synchronized void unread() {
filePosition--;
}
//
// Write primitives.
//
/**
* Write a byte to the file. If the file has not been opened for writing, an IOException will be
* raised only when an attempt is made to write the buffer to the file.
* <p>
* Caveat: the effects of seek( )ing beyond the end of the file are undefined.
*
* @param b
* _more_
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized void write(int b) throws IOException {
// If the file position is within the block of data...
if (filePosition < dataEnd) {
buffer[(int) (filePosition++ - bufferStart)] = (byte) b;
bufferModified = true;
// ...or (assuming that seek will not allow the file pointer
// to move beyond the end of the file) get the correct block of
// data...
} else {
// If there is room in the buffer, expand it...
if (dataSize != buffer.length) {
buffer[(int) (filePosition++ - bufferStart)] = (byte) b;
bufferModified = true;
dataSize++;
dataEnd++;
// ...or do another seek to get a new buffer, and start again...
} else {
seek(filePosition);
write(b);
}
}
}
/**
* Write <code>len</code> bytes from an array to the file.
*
* @param b
* the array containing the data.
* @param off
* the offset in the array to the data.
* @param len
* the length of the data.
* @exception IOException
* if an I/O error occurrs.
*/
public synchronized void writeBytes(byte b[], int off, int len) throws IOException {
// If the amount of data is small (less than a full buffer)...
if (len < buffer.length) {
// If any of the data fits within the buffer...
int spaceInBuffer = 0;
int copyLength = 0;
if (filePosition >= bufferStart) {
spaceInBuffer = (int) ((bufferStart + buffer.length)
- filePosition);
}
if (spaceInBuffer > 0) {
// Copy as much as possible to the buffer.
copyLength = (spaceInBuffer > len) ? len : spaceInBuffer;
System.arraycopy(b, off, buffer,
(int) (filePosition - bufferStart), copyLength);
bufferModified = true;
long myDataEnd = filePosition + copyLength;
dataEnd = (myDataEnd > dataEnd) ? myDataEnd : dataEnd;
dataSize = (int) (dataEnd - bufferStart);
filePosition += copyLength;
}
// If there is any data remaining, move to the new position and copy to
// the new buffer.
if (copyLength < len) {
seek(filePosition); // triggers a flush
System.arraycopy(b, off + copyLength, buffer,
(int) (filePosition - bufferStart), len - copyLength);
bufferModified = true;
long myDataEnd = filePosition + (len - copyLength);
dataEnd = (myDataEnd > dataEnd) ? myDataEnd : dataEnd;
dataSize = (int) (dataEnd - bufferStart);
filePosition += (len - copyLength);
}
// ...or write a lot of data...
} else {
// Flush the current buffer, and write this data to the file.
if (bufferModified) {
flush();
bufferStart = dataEnd = dataSize = 0;
// file.seek(filePosition); // JC added Oct 21, 2004
}
file.seek(filePosition); // moved per Steve Cerruti; Jan 14, 2005
file.write(b, off, len);
filePosition += len;
}
}
/**
* Writes <code>b.length</code> bytes from the specified byte array starting at offset
* <code>off</code> to this file.
*
* @param b
* the data.
* @exception IOException
* if an I/O error occurs.
*/
public void write(byte b[]) throws IOException {
writeBytes(b, 0, b.length);
}
/**
* Writes <code>len</code> bytes from the specified byte array starting at offset
* <code>off</code> to this file.
*
* @param b
* the data.
* @param off
* the start offset in the data.
* @param len
* the number of bytes to write.
* @exception IOException
* if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
writeBytes(b, off, len);
}
//
// DataInput methods.
//
/**
* Reads a <code>boolean</code> from this file. This method reads a single byte from the file.
* A value of <code>0</code> represents <code>false</code>. Any other value represents
* <code>true</code>. This method blocks until the byte is read, the end of the stream is
* detected, or an exception is thrown.
*
* @return the <code>boolean</code> value read.
* @exception IOException if an I/O error occurs.
*/
public final boolean readBoolean() throws IOException {
int ch = this.read();
if (ch < 0) {
throw new EOFException();
}
return (ch != 0);
}
/**
* Reads a signed 8-bit value from this file. This method reads a byte from the file. If the
* byte read is <code>b</code>, where <code>0 <= b <= 255</code>,
* then the result is:
* <ul>
* {@code (byte)(b)}
* </ul>
* <p>
* This method blocks until the byte is read, the end of the stream is detected, or an exception
* is thrown.
*
* @return the next byte of this file as a signed 8-bit <code>byte</code>.
* @exception IOException if an I/O error occurs.
*/
public final byte readByte() throws IOException {
int ch = this.read();
if (ch < 0) {
throw new EOFException();
}
return (byte) (ch);
}
/**
* Reads an unsigned 8-bit number from this file. This method reads a byte from this file and
* returns that byte.
* <p>
* This method blocks until the byte is read, the end of the stream is detected, or an exception
* is thrown.
*
* @return the next byte of this file, interpreted as an unsigned 8-bit number.
* @exception IOException if an I/O error occurs.
*/
public final int readUnsignedByte() throws IOException {
int ch = this.read();
if (ch < 0) {
throw new EOFException();
}
return ch;
}
/**
* Reads a signed 16-bit number from this file. The method reads 2 bytes from this file. If the
* two bytes read, in order, are <code>b1</code> and <code>b2</code>, where each of the two
* values is between <code>0</code> and <code>255</code>, inclusive, then the result is
* equal to:
* <ul>
* {@code (short)((b1 << 8) | b2)}
* </ul>
* <p>
* This method blocks until the two bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next two bytes of this file, interpreted as a signed 16-bit number.
* @exception IOException if an I/O error occurs.
*/
public synchronized final short readShort() throws IOException {
int ch1 = this.read();
int ch2 = this.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
if (bigEndian) {
return (short) ((ch1 << 8) + (ch2 << 0));
} else {
return (short) ((ch2 << 8) + (ch1 << 0));
}
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public final void readShort(short[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
pa[start + i] = readShort();
}
}
/**
* Reads an unsigned 16-bit number from this file. This method reads two bytes from the file. If
* the bytes read, in order, are <code>b1</code> and <code>b2</code>, where
* <code>0 <= b1, b2 <= 255</code>, then the result is equal to:
* <ul>
* {@code (b1 << 8) | b2}
* </ul>
* <p>
* This method blocks until the two bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next two bytes of this file, interpreted as an unsigned 16-bit integer.
* @exception IOException if an I/O error occurs.
*/
public synchronized final int readUnsignedShort() throws IOException {
int ch1 = this.read();
int ch2 = this.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
if (bigEndian) {
return ((ch1 << 8) + (ch2 << 0));
} else {
return ((ch2 << 8) + (ch1 << 0));
}
}
/**
* Reads a Unicode character from this file. This method reads two bytes from the file. If the
* bytes read, in order, are <code>b1</code> and <code>b2</code>, where
* <code>0 <= b1, b2 <= 255</code>, then the result is equal
* to:
* <ul>
* {@code (char)((b1 << 8) | b2)}
* </ul>
* <p>
* This method blocks until the two bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next two bytes of this file as a Unicode character.
* @exception IOException if an I/O error occurs.
*/
public synchronized final char readChar() throws IOException {
int ch1 = this.read();
int ch2 = this.read();
if ((ch1 | ch2) < 0) {
throw new EOFException();
}
if (bigEndian) {
return (char) ((ch1 << 8) + (ch2 << 0));
} else {
return (char) ((ch2 << 8) + (ch1 << 0));
}
}
/**
* Reads a signed 32-bit integer from this file. This method reads 4 bytes from the file. If the
* bytes read, in order, are <code>b1</code>, <code>b2</code>, <code>b3</code>, and
* <code>b4</code>, where <code>0 <= b1, b2, b3, b4 <= 255</code>,
* then the result is equal to:
* <ul>
* {@code (b1 << 24) | (b2 << 16) + (b3 << 8) + b4}
* </ul>
* <p>
* This method blocks until the four bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next four bytes of this file, interpreted as an <code>int</code>.
* @exception IOException if an I/O error occurs.
*/
public synchronized final int readInt() throws IOException {
int ch1 = this.read();
int ch2 = this.read();
int ch3 = this.read();
int ch4 = this.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) {
throw new EOFException();
}
if (bigEndian) {
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
} else {
return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
}
}
/**
* Read an integer at the given position, bypassing all buffering.
*
* @param pos
* read a byte at this position
* @return The int that was read
* @throws IOException if the end of file was reached
*/
public final int readIntUnbuffered(long pos) throws IOException {
byte[] bb = new byte[4];
read_(pos, bb, 0, 4);
int ch1 = bb[0] & 0xff;
int ch2 = bb[1] & 0xff;
int ch3 = bb[2] & 0xff;
int ch4 = bb[3] & 0xff;
if ((ch1 | ch2 | ch3 | ch4) < 0) {
throw new EOFException();
}
if (bigEndian) {
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
} else {
return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
}
}
/**
* Reads a signed 24-bit integer from this file. This method reads 3 bytes from the file. If the
* bytes read, in order, are <code>b1</code>, <code>b2</code>, and <code>b3</code>,
* where <code>0 <= b1, b2, b3 <= 255</code>, then the result is
* equal to:
* <ul>
* {@code (b1 << 16) | (b2 << 8) + (b3 << 0)}
* </ul>
* <p>
* This method blocks until the three bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @exception IOException if an I/O error occurs.
*/
public final void readInt(int[] pa, int start, int n) throws IOException {
for (int i = 0; i < n; i++) {
pa[start + i] = readInt();
}
}
/**
* Reads a signed 64-bit integer from this file. This method reads eight bytes from the file. If
* the bytes read, in order, are <code>b1</code>, <code>b2</code>, <code>b3</code>,
* <code>b4</code>, <code>b5</code>, <code>b6</code>, <code>b7</code>, and
* <code>b8,</code> where:
* <ul>
* {@code 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <=255,}
* </ul>
* <p>
* then the result is equal to:
* <p>
* <blockquote>
*
* <pre>
*
* ((long) b1 << 56) + ((long) b2 << 48)
*
* + ((long) b3 << 40) + ((long) b4 << 32)
*
* + ((long) b5 << 24) + ((long) b6 << 16)
*
* + ((long) b7 << 8) + b8
*
* </pre>
*
* </blockquote>
* <p>
* This method blocks until the eight bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next eight bytes of this file, interpreted as a <code>long</code>.
* @exception IOException if an I/O error occurs.
*/
public synchronized final long readLong() throws IOException {
if (bigEndian) {
return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL); // tested ok
} else {
//(long)
return ((readInt() & 0xFFFFFFFFL)
+ ((long) readInt() << 32)); // not tested yet ??
}
/*
* int ch1 = this.read(); int ch2 = this.read(); int ch3 = this.read(); int ch4 =
* this.read(); int ch5 = this.read(); int ch6 = this.read(); int ch7 = this.read(); int ch8 =
* this.read(); if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) throw new
* EOFException(); if (bigEndian) return ((long)(ch1 << 56)) + (ch2 << 48) + (ch3 << 40) +
* (ch4 << 32) + (ch5 << 24) + (ch6 << 16) + (ch7 << 8) + (ch8 << 0)); else return
* ((long)(ch8 << 56) + (ch7 << 48) + (ch6 << 40) + (ch5 << 32) + (ch4 << 24) + (ch3 <<
* 16) + (ch2 << 8) + (ch1 << 0));
*/
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void readLong(long[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
pa[start + i] = readLong();
}
}
/**
* Reads a <code>float</code> from this file. This method reads an <code>int</code> value as
* if by the <code>readInt</code> method and then converts that <code>int</code> to a
* <code>float</code> using the <code>intBitsToFloat</code> method in class
* <code>Float</code>.
* <p>
* This method blocks until the four bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next four bytes of this file, interpreted as a <code>float</code>.
* @see java.io.RandomAccessFile#readInt()
* @see java.lang.Float#intBitsToFloat(int)
* @exception IOException if an I/O error occurs.
*/
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void readFloat(float[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
pa[start + i] = Float.intBitsToFloat(readInt());
}
}
/**
* Reads a <code>double</code> from this file. This method reads a <code>long</code> value
* as if by the <code>readLong</code> method and then converts that <code>long</code> to a
* <code>double</code> using the <code>longBitsToDouble</code> method in class
* <code>Double</code>.
* <p>
* This method blocks until the eight bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return the next eight bytes of this file, interpreted as a <code>double</code>.
* @see java.io.RandomAccessFile#readLong()
* @see java.lang.Double#longBitsToDouble(long)
* @exception IOException if an I/O error occurs.
*/
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void readDouble(double[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
pa[start + i] = Double.longBitsToDouble(readLong());
}
}
/**
* Reads the next line of text from this file. This method successively reads bytes from the
* file until it reaches the end of a line of text.
* <p>
* A line of text is terminated by a carriage-return character (<code>'\r'</code>), a
* newline character (<code>'\n'</code>), a carriage-return character immediately
* followed by a newline character, or the end of the input stream. The line-terminating
* character(s), if any, are included as part of the string returned.
* <p>
* This method blocks until a newline character is read, a carriage return and the byte
* following it are read (to see if it is a newline), the end of the stream is detected, or an
* exception is thrown.
*
* @return the next line of text from this file.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final String readLine() throws IOException {
StringBuffer input = new StringBuffer();
int c;
while (((c = read()) != -1) && (c != '\n')) {
input.append((char) c);
}
if ((c == -1) && (input.length() == 0)) {
return null;
}
return input.toString();
}
/**
* Reads in a string from this file. The string has been encoded using a modified UTF-8 format.
* <p>
* The first two bytes are read as if by <code>readUnsignedShort</code>. This value gives the
* number of following bytes that are in the encoded string, not the length of the resulting
* string. The following bytes are then interpreted as bytes encoding characters in the UTF-8
* format and are converted into characters.
* <p>
* This method blocks until all the bytes are read, the end of the stream is detected, or an
* exception is thrown.
*
* @return a Unicode string.
* @see java.io.RandomAccessFile#readUnsignedShort()
* @exception IOException if an I/O error occurs.
*/
public final String readUTF() throws IOException {
return DataInputStream.readUTF(this);
}
/**
* Read a String of knoen length.
*
* @param nbytes
* number of bytes to read
* @return String wrapping the bytes.
* @throws IOException
* if this file reaches the end before reading all the bytes or
* a general I/0 error occurs
*/
public String readString(int nbytes) throws IOException {
byte[] data = new byte[nbytes];
readFully(data);
return new String(data);
}
//
// DataOutput methods.
//
/**
* Writes a <code>boolean</code> to the file as a 1-byte value. The value <code>true</code>
* is written out as the value <code>(byte)1</code>; the value <code>false</code> is
* written out as the value <code>(byte)0</code>.
*
* @param v
* a <code>boolean</code> value to be written.
* @exception IOException
* if an I/O error occurs.
*/
public final void writeBoolean(boolean v) throws IOException {
write(v ? 1 : 0);
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeBoolean(boolean[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeBoolean(pa[start + i]);
}
}
/**
* Writes a <code>byte</code> to the file as a 1-byte value.
*
* @param v
* a <code>byte</code> value to be written.
* @exception IOException
* if an I/O error occurs.
*/
public final void writeByte(int v) throws IOException {
write(v);
}
/**
* Writes a <code>short</code> to the file as two bytes, high byte first.
*
* @param v
* a <code>short</code> to be written.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final void writeShort(int v) throws IOException {
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeShort(short[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeShort(pa[start + i]);
}
}
/**
* Writes a <code>char</code> to the file as a 2-byte value, high byte first.
*
* @param v
* a <code>char</code> value to be written.
* @exception IOException
* if an I/O error occurs.
*/
public final void writeChar(int v) throws IOException {
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeChar(char[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeChar(pa[start + i]);
}
}
/**
* Writes an <code>int</code> to the file as four bytes, high byte first.
*
* @param v
* an <code>int</code> to be written.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final void writeInt(int v) throws IOException {
write((v >>> 24) & 0xFF);
write((v >>> 16) & 0xFF);
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeInt(int[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeInt(pa[start + i]);
}
}
/**
* Writes a <code>long</code> to the file as eight bytes, high byte first.
*
* @param v
* a <code>long</code> to be written.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final void writeLong(long v) throws IOException {
write((int) (v >>> 56) & 0xFF);
write((int) (v >>> 48) & 0xFF);
write((int) (v >>> 40) & 0xFF);
write((int) (v >>> 32) & 0xFF);
write((int) (v >>> 24) & 0xFF);
write((int) (v >>> 16) & 0xFF);
write((int) (v >>> 8) & 0xFF);
write((int) (v >>> 0) & 0xFF);
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeLong(long[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeLong(pa[start + i]);
}
}
/**
* Converts the float argument to an <code>int</code> using the <code>floatToIntBits</code>
* method in class <code>Float</code>, and then writes that <code>int</code> value to the
* file as a 4-byte quantity, high byte first.
*
* @param v a <code>float</code> value to be written.
* @see java.lang.Float#floatToIntBits(float)
* @exception IOException if an I/O error occurs.
*/
public final void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeFloat(float[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeFloat(pa[start + i]);
}
}
/**
* Converts the double argument to a <code>long</code> using the <code>doubleToLongBits</code>
* method in class <code>Double</code>, and then writes that <code>long</code> value to the
* file as an 8-byte quantity, high byte first.
*
* @param v a <code>double</code> value to be written.
* @see java.lang.Double#doubleToLongBits(double)
* @exception IOException if an I/O error occurs.
*/
public final void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
/**
* _more_.
*
* @param pa _more_
* @param start _more_
* @param n _more_
* @throws IOException _more_
*/
public synchronized final void writeDouble(double[] pa, int start, int n)
throws IOException {
for (int i = 0; i < n; i++) {
writeDouble(pa[start + i]);
}
}
/**
* Writes the string to the file as a sequence of bytes. Each character in the string is written
* out, in sequence, by discarding its high eight bits.
*
* @param s
* a string of bytes to be written.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final void writeBytes(String s) throws IOException {
int len = s.length();
for (int i = 0; i < len; i++) {
write((byte) s.charAt(i));
}
}
/**
* Writes the character array to the file as a sequence of bytes. Each character in the string
* is written out, in sequence, by discarding its high eight bits.
*
* @param b
* a character array of bytes to be written.
* @param off
* the index of the first character to write.
* @param len
* the number of characters to write.
* @exception IOException
* if an I/O error occurs.
*/
public synchronized final void writeBytes(char b[], int off, int len)
throws IOException {
for (int i = off; i < len; i++) {
write((byte) b[i]);
}
}
/**
* Writes a string to the file as a sequence of characters. Each character is written to the
* data output stream as if by the <code>writeChar</code> method.
*
* @param s a <code>String</code> value to be written.
* @see java.io.RandomAccessFile#writeChar(int)
* @exception IOException if an I/O error occurs.
*/
public synchronized final void writeChars(String s) throws IOException {
int len = s.length();
for (int i = 0; i < len; i++) {
int v = s.charAt(i);
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
}
}
/**
* Writes a string to the file using UTF-8 encoding in a machine-independent manner.
* <p>
* First, two bytes are written to the file as if by the <code>writeShort</code> method giving
* the number of bytes to follow. This value is the number of bytes actually written out, not
* the length of the string. Following the length, each character of the string is output, in
* sequence, using the UTF-8 encoding for each character.
*
* @param str
* a string to be written.
* @exception IOException
* if an I/O error occurs.
*/
public final void writeUTF(String str) throws IOException {
int strlen = str.length();
int utflen = 0;
for (int i = 0; i < strlen; i++) {
int c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
utflen++;
} else if (c > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
if (utflen > 65535) {
throw new UTFDataFormatException();
}
write((utflen >>> 8) & 0xFF);
write((utflen >>> 0) & 0xFF);
for (int i = 0; i < strlen; i++) {
int c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
write(c);
} else if (c > 0x07FF) {
write(0xE0 | ((c >> 12) & 0x0F));
write(0x80 | ((c >> 6) & 0x3F));
write(0x80 | ((c >> 0) & 0x3F));
} else {
write(0xC0 | ((c >> 6) & 0x1F));
write(0x80 | ((c >> 0) & 0x3F));
}
}
}
/**
* Create a string representation of this object.
*
* @return a string representation of the state of the object.
*/
public String toString() {
return "fp=" + filePosition + ", bs=" + bufferStart + ", de="
+ dataEnd + ", ds=" + dataSize + ", bl=" + buffer.length
+ ", readonly=" + readonly + ", bm=" + bufferModified;
}
/** Support for ucar.unidata.io.FileCache. */
protected boolean cached;
/**
* Set whether this fie is in the cache.
*
* @param cached
* in the cache or not.
* @see <a href="https://www.unidata.ucar.edu/software/thredds/v4.3/netcdf-java/v4.3/javadoc/ucar/unidata/io/RandomAccessFile.html">ucar.unidata.io.FileCache</a>
*/
public void setCached(boolean cached) {
this.cached = cached;
}
/**
* Find whether this fie is in the cache.
*
* @return true if in the cache.
* @see <a href="https://www.unidata.ucar.edu/software/thredds/v4.3/netcdf-java/v4.3/javadoc/ucar/unidata/io/RandomAccessFile.html">ucar.unidata.io.FileCache</a>
*/
public boolean isCached() {
return cached;
}
/**
* _more_.
*
* @throws IOException _more_
*/
public void synch() throws IOException {
}
/**
* Test the byte operations of the RandomAccessFile class. These are the methods that read/write
* on a byte-by-byte basis. The following checks are made:
* <ul>
* <li>Writing random bytes to a file.
* <li>Checking the size of the file is correct.
* <li>Checking that EOF is correctly raised.
* <li>Reading the file back in and verifying its contents.
* </ul>
* The test file is 4.5 times the size of the buffer, in order to test paging between buffers,
* and using files that end in the middle of a buffer. A constant seed value is used for the
* random number generator, to ensure any bugs are reproduceable.
*
* @param filename
* the name of the test file to generate.
* @param bufferSize
* the size of the buffer to use. public static void testBytes( String filename, int
* bufferSize ) { System.out.println( "\nTesting byte operations..." ); int
* newFileSize = (int)(bufferSize * 4.5 ); try { // Create a test file.
* RandomAccessFile outFile = new RandomAccessFile( filename, RandomAccessFile.WRITE |
* RandomAccessFile.CREATE, bufferSize ); try { Random random = new Random( 0 ); byte
* b = 0; for( int i = 0; i < newFileSize; i++ ) { b = (byte)(random.nextInt( ) %
* 256); outFile.writeByte( b ); } } finally { outFile.close( ); } // Check that the
* file length is correct. if( (new File( filename )).length( ) == newFileSize )
* System.out.println( ". File size correct (" + newFileSize + ")." ); else
* System.out.println( "X New file size incorrect (should be " + newFileSize + ", but
* is " + (new File( filename )).length( ) + ")." ); // Read the file, verify and
* modify its contents. RandomAccessFile inoutFile = new RandomAccessFile( filename,
* RandomAccessFile.READ | RandomAccessFile.WRITE, bufferSize ); boolean verified =
* true; int byteNo = 0; try { // Read each byte in the file. Random random = new
* Random( 0 ); byte b = 0; for( byteNo = 0; byteNo < newFileSize; byteNo++ ) { b =
* (byte)(random.nextInt( ) % 256); byte currentByte = inoutFile.readByte( ); //
* Check the value is correct. if( currentByte != b ) verified = false; // Modify
* selected values. if( currentByte >=128 ) { inoutFile.seek(
* inoutFile.getFilePointer( ) - 1 ); inoutFile.writeByte( 0 ); } } // Check the EOF
* is correctly trapped. boolean foundEOF = false; try { inoutFile.readByte( ); }
* catch( EOFException e ) { foundEOF = true; } if( foundEOF ) System.err.println( ".
* EOF found correctly" ); else System.err.println( "X No EOF found." ); // Trace a
* premature EOF. } catch( EOFException e ) { e.printStackTrace( );
* System.err.println( " At byte " + byteNo ); } finally { inoutFile.close( ); } //
* Check that the read was verified. if( verified ) System.out.println( ". Read/Write
* verified" ); else System.out.println( "X Read/Write verification failed" ); //
* Read the file and verify contents. RandomAccessFile inFile = new RandomAccessFile(
* filename, RandomAccessFile.READ, bufferSize ); verified = true; byteNo = 0; try { //
* Read each byte in the file. Random random = new Random( 0 ); byte b = 0; for(
* byteNo = 0; byteNo < newFileSize; byteNo++ ) { b = (byte)(random.nextInt( ) %
* 256); byte currentByte = inFile.readByte( ); // Account for the modification. if(
* currentByte >= 128 ) currentByte = 0; // Check the byte's value. if( currentByte !=
* b ) verified = false; } // Trap a premature EOF. } catch( EOFException e ) {
* e.printStackTrace( ); System.err.println( " At byte " + byteNo ); } finally {
* inFile.close( ); } // Check that the read was verified. if( verified )
* System.out.println( ". Update verified" ); else System.out.println( "X Update
* verification failed" ); } catch( Exception e ) { e.printStackTrace( ); } } Test
* the block operations of the RandomAccessFile class. These are the methods that
* read/write blocks of data. The following checks are made:
* <ul>
* <li>Writing blocks of data that are smaller than the buffer size.
* <li>Writing blocks of data that are larger than the buffer size.
* <li>Checking the size of the file is correct.
* <li>Reading small blocks of the file back in and verifying its contents.
* <li>Reading large blocks of the file back in and verifying its contents.
* </ul>
* @param filename
* the name of the test file to generate. public static void testBlocks( String
* filename ) { System.err.println( "\nTesting block operations..." ); // Generate
* the data. int bufferSize = 10; byte data[] = new byte[256]; for( int i = 0; i <
* data.length; i++ ) data[i] = (byte)(i % 256); try { // Write the data in small and
* large blocks. RandomAccessFile outFile = new RandomAccessFile( filename,
* RandomAccessFile.WRITE | RandomAccessFile.CREATE, bufferSize ); for( int i = 0; i <
* data.length; ) { int blockSize = (i < data.length / 2) ? 3 : 13 ; blockSize = (i +
* blockSize >= data.length) ? (data.length - i) : blockSize; outFile.write( data, i,
* blockSize ); i += blockSize; } outFile.close( ); // Check that the file length is
* correct. if( (new File( filename )).length( ) != data.length ) System.out.println(
* "X New file size incorrect (should be " + data.length + ", but is " + (new File(
* filename )).length( ) + ")." ); else System.out.println( ". File size correct (" +
* data.length + ")." ); // Reopen the file for reading. RandomAccessFile inFile =
* new RandomAccessFile( filename, RandomAccessFile.READ, bufferSize ); // Read and
* check random small blocks of data. boolean verified = true; int firstFailure =
* 256; Random random = new Random( 0 ); byte block[] = new byte[(int)(bufferSize *
* 0.5)]; for( int i = 0; i < 100; i++ ) { int index = Math.abs( random.nextInt( ) ) %
* (data.length - block.length); inFile.seek( index ); inFile.read( block ); //
* Verify the block of data. for( int j = 0; j < block.length; j++ ) { if( block[j] !=
* data[index + j] ) { verified = false; if( index + j < firstFailure ) firstFailure =
* index + j; } } } if( verified ) System.err.println( ". Reading small blocks
* verified." ); else System.err.println( "X Reading small blocks failed (byte " +
* firstFailure + ")." ); // Read and check random large (bigger than the bufferSize)
* blocks // of data. verified = true; random = new Random( 0 ); block = new
* byte[(int)(bufferSize * 1.5)]; for( int i = 0; i < 100; i++ ) { int index =
* Math.abs( random.nextInt( ) ) % (data.length - block.length); inFile.seek( index );
* inFile.read( block ); // Verify the block of data. for( int j = 0; j <
* block.length; j++ ) { if( block[j] != data[j + index] ) verified = false; } } if(
* verified ) System.err.println( ". Reading large blocks verified." ); else
* System.err.println( "X Reading large blocks failed." ); // Close the input file.
* inFile.close( ); } catch( Exception e ) { e.printStackTrace( ); } } Benchmark the
* performance of the new RandomAccessFile class. Its speed is compared to that of a
* java.io.RandomAccessFile, based on reading and writing a test file, byte by byte.
* @param filename
* the name of the test file.
* @param bufferSize
* the buffer size to use. public static void benchmark( String filename, int
* bufferSize ) { System.out.println( "\nBenchmarking..." ); // Start the clock, and
* open a file for reading and a file for writing. long time = (new Date( )).getTime( );
* try { RandomAccessFile inFile = new RandomAccessFile( filename,
* RandomAccessFile.READ, bufferSize ); RandomAccessFile outFile = new
* RandomAccessFile( "temp.data", RandomAccessFile.WRITE | RandomAccessFile.CREATE,
* bufferSize ); // Copy one file to the other. try { while( true ) {
* outFile.writeByte( inFile.readByte( ) ); } } catch( EOFException e ) { } catch(
* IOException e ) { e.printStackTrace( ); } finally { inFile.close( );
* outFile.close( ); } System.out.println( ". RandomAccessFile elapsed time=" + ((new
* Date( )).getTime( ) - time) ); // Restart the clock, and open RandomAccessFiles
* for reading and writing. time = (new Date( )).getTime( ); java.io.RandomAccessFile
* inFile2 = new java.io.RandomAccessFile( filename, "r" ); java.io.RandomAccessFile
* outFile2 = new java.io.RandomAccessFile( "temp.data", "rw" ); // Copy one file to
* the other. try { while( true ) { outFile2.writeByte( inFile2.readByte( ) ); } }
* catch( EOFException e ) { } catch( IOException e ) { e.printStackTrace( ); }
* finally { inFile2.close( ); outFile2.close( ); } } catch( Exception e ) {
* e.printStackTrace( ); } System.out.println( ". java.io.RandomAccessFile elapsed
* time=" + ((new Date( )).getTime( ) - time) ); } Test the RandomAccessFile class.
* This involves testing the byte methods, the block methods, and benchmarking the
* performance. By appending 'test' or 'benchmark' to the command-line, it can be
* limited to the tests or benchmarking alone. The test filename is only used for the
* benchmarking, the other tests create a file called "temp.data" in the current
* directory. Note that the size of the buffer determines the size of the test file
* (which is 4.5 times the size of the buffer).
* @param argv
* Usage: <testFilename> [bufferSize] [test | benchmark]
* @see #testBytes(String filename, int bufferSize)
* @see #testBlocks(String filename)
* @see #benchmark(String filename, int bufferSize) public static void main( String argv[] ) {
* int defaultPageSize = 4096; // Parse the command-line arguments. String filename = null;
* int bufferSize = 0; boolean test = true; boolean benchmark = true; if( argv.length < 1 ) {
* System.err.println( "Usage: RandomAccessFile <filename> [buffer.length] [benchmark |
* test]" ); System.exit( -1 ); } else if( argv.length < 2 ) { filename = argv[0];
* bufferSize = defaultPageSize; } else if( argv.length < 3 ) { filename = argv[0];
* bufferSize = Integer.parseInt( argv[1] ); } else { filename = argv[0]; bufferSize =
* Integer.parseInt( argv[1] ); if( argv[2].equals( "benchmark" ) ) test = false; else if(
* argv[2].equals( "test" ) ) benchmark = false; } System.out.println(
* "\nRandomAccessFile\n" + "========================" ); System.out.println( "filename=" +
* filename + ", bufferSize=" + bufferSize ); System.out.println( "totalMemory=" +
* (Runtime.getRuntime( ).totalMemory( ) / 1000) + "k" + " freeMemory=" +
* (Runtime.getRuntime( ).freeMemory( ) / 1000) + "k" ); if( test ) {
* RandomAccessFile.testBytes( "temp.data", bufferSize ); RandomAccessFile.testBlocks(
* "temp.data" ); } if( benchmark ) { RandomAccessFile.benchmark( filename, bufferSize ); }
* System.out.println( "\nEND" ); }
*/
}
/*
* Change History: $Log: RandomAccessFile.java,v $ Revision 1.33 2006/03/25 00:20:13 caron ** empty
* log message *** Revision 1.32 2006/03/09 22:18:47 caron bug fixes for sync, dods. Revision 1.31
* 2006/01/13 18:55:22 jeffmc fix javadoc errors Revision 1.30 2006/01/11 16:15:47 caron syncExtend
* N3iosp, FileWriter writes by record Revision 1.29 2005/10/16 20:46:39 caron remove debugging
* messages Revision 1.28 2005/10/15 23:59:50 caron fix bug in truncating non-netcdf3 files Revision
* 1.27 2005/10/11 19:39:52 caron RAF can be optionally cached HttpRAF detects if server supports
* range bytes Revision 1.26 2005/08/26 00:32:41 caron deal with NetCDF "non-canonical length" files
* Revision 1.25 2005/08/09 23:35:33 caron ** empty log message *** Revision 1.24 2005/07/29
* 00:30:54 caron null file when closing to help gc Revision 1.23 2005/07/25 00:07:06 caron cache
* debugging Revision 1.22 2005/04/18 23:45:57 caron _unsigned FileCache minFileLength Revision 1.21
* 2005/03/21 22:07:18 caron add setMinLength() method Revision 1.20 2005/01/14 23:20:48 caron seek
* to filePosition before write Revision 1.19 2005/01/14 21:41:37 caron ** empty log message ***
* Revision 1.18 2004/12/08 18:09:23 caron add isAtEndOfFile() Revision 1.17 2004/10/23 21:36:12
* caron no message Revision 1.16 2004/10/22 00:50:46 caron fix long-standing bug in writeBytes()
* Revision 1.15 2004/10/20 23:23:15 caron add nexrad2 iosp Revision 1.14 2004/10/12 22:03:46
* rkambic added readInt3Bytes and readUint3Bytes Revision 1.13 2004/10/12 14:12:04 rkambic added
* getInt3Bytes() Revision 1.12 2004/10/12 02:57:06 caron refactor for grib1/grib2: move common
* functionality up to ucar.grib split GribServiceProvider Revision 1.11 2004/10/06 19:03:45 caron
* clean up javadoc change useV3 -> useRecordsAsStructure remove id, title, from NetcdfFile
* constructors add "in memory" NetcdfFile Revision 1.10 2004/10/02 20:56:03 caron keep track of
* location URL Revision 1.9 2004/09/24 02:32:02 caron grib2 reading Revision 1.8 2004/09/22
* 21:24:08 caron common io for nc22, grib, etc Revision 1.5 2004/08/16 21:41:36 caron ** empty log
* message *** Revision 1.3 2004/07/12 23:40:17 caron 2.2 alpha 1.0 checkin Revision 1.2 2004/07/06
* 19:28:10 caron pre-alpha checkin Revision 1.1.1.1 2003/12/04 21:05:27 caron checkin 2.2
*/