Universal Integer Reader/Writer

There are a wide variety of ways to read and write integers to a file. This code fragment enhances Java's RandomAccessFile to encompass a wider variety of methods, including 1, 2 and 4 byte integers, and both signed and unsigned values.

By default Java values are always signed values, and multi-byte values are always big-endian. In the real world, however, many times you will need to read or write to files with integer types that are unsigned, or little-endian. Here, I have expanded Java's RandomAccessFile to include a more universal file reading and writing mechanism. It's important to remember, though, that the data type may not be what you expect. For instance, reading a 1-byte integer, results in an int data type, not a byte. This is because Java can't express an unsigned byte using a byte type. There are similar type changes in 2 and 4 byte values as well.

public class KlangRAF extends RandomAccessFile {

	public KlangRAF(String name, String mode) throws FileNotFoundException {
		super(name, mode);
	}
	
	public KlangRAF(File file, String mode) throws FileNotFoundException {
		super(file, mode);
	}
	
	/**
	 * Read a one-byte integer value.
	 * 
	 * @param signed if true, value will be signed
	 * @return the one-byte value as an int
	 * @throws IOException if read error occurs
	 */
	public int read1ByteInt(boolean signed) throws IOException {
		if (signed) {
			return (int)this.readByte();
		} else {
			return this.readUnsignedByte();
		}
	}
	
	/**
	 * Write a one-byte integer value. Will work correctly with either a signed or unsigned value.
	 * 
	 * @param value the byte value to write
	 * @throws IOException if value is out of range or write error occurs
	 */
	public void write1ByteInt(int value) throws IOException {
		if ((value  255)) {
			throw new IOException("Int value is out of range");
		}
		if (value >= 128) {
			value = value - 256;
		}
		this.writeByte(value);
	}
	
	/**
	 * Read a two-byte integer value.
	 * 
	 * @param signed if true, value will be signed
	 * @param isBigEndian if true, value will be read as a big-endian value; false for small-endian
	 * @return the two-byte value as an int
	 * @throws IOException if read error occurs
	 */
	public int read2ByteInt(boolean signed, boolean isBigEndian) throws IOException {
		if (signed) {
			if (isBigEndian) {
				return (int)this.readShort();
			} else {
				short val = this.readShort();
				val = Short.reverseBytes(val);
				return (int)val;
			}
		} else {
			if (isBigEndian) {
				short val = this.readShort();
				int output = val & 0xffff;
				return output;
			} else {
				short val = this.readShort();
				val = Short.reverseBytes(val);
				int output = val & 0xffff;
				return output;
			}
		}
	}
	
	/**
	 * Write a 2-byte integer to a file
	 * 
	 * @param value the value expressed as an integer
	 * @param signed whether the value should be written as a signed or unsigned value
	 * @param isBigEndian true if the value should be written as big-endian, false for small-endian
	 * @throws IOException if value is out of range, or a write error occurs
	 */
	public void write2ByteInt(int value, boolean signed, boolean isBigEndian) throws IOException {
		if (signed) {
			if ((value < -32768) || (value > 32767)) {
				throw new IOException("Int value is out of range");
			}
		} else {
			if ((value < 0) || (value > 65535)) {
				throw new IOException("Int value is out of range");
			}
		}
		if (signed) {
			if (isBigEndian) {
				this.writeShort(value);
				return;
			} else {
				short output = Short.reverseBytes((short)value);
				this.writeShort(output);
			}
		} else {
			if (isBigEndian) {
				short output = (short)(value & 0xffff);
				this.writeShort(output);
			} else {
				short output = (short)(value & 0xffff);
				output = Short.reverseBytes(output);
				this.writeShort(output);
			}
		}
	}
	
	/**
	 * Read a four-byte integer value. Since unsigned values can exceed the capacity of an int, 
         * this value is stored as a long.
	 * 
	 * @param signed if true, value will be signed
	 * @param isBigEndian if true, value will be read as a big-endian value; false for small-endian
	 * @return the two-byte value as a long
	 * @throws IOException if read error occurs
	 */
	public long read4ByteInt(boolean signed, boolean isBigEndian) throws IOException {
		if (signed) {
			if (isBigEndian) {
				return (long)this.readInt();
			} else {
				int input = this.readInt();
				input = Integer.reverseBytes(input);
				return (long)input;
			}
		} else {
			if (isBigEndian) {
				int val = this.readInt();
				long output = val & 0xffffffffL;
				return output;
			} else {
				int val = this.readInt();
				val = Integer.reverseBytes(val);
				long output = val & 0xffffffffL;	
				return output;
			}
		}
	}
	
	/**
	 * Write a 4-byte integer to a file.
	 * 
	 * @param value the value expressed as a long
	 * @param signed whether the value should be written as a signed or unsigned value
	 * @param isBigEndian true if the value should be written as big-endian, false for small-endian
	 * @throws IOException if value is out of range, or a write error occurs
	 */
	public void write4ByteInt(long value, boolean signed, boolean isBigEndian) throws IOException {
		if (signed) {			
			if ((value < -2147483648) || (value > 2147483647)) {
				throw new IOException("Long value is out of range");
			}
		} else {
			if ((value < 0) || (value > 4294967295L)) {
				throw new IOException("Long value is out of range");
			}
		}
		if (signed) {
			if (isBigEndian) {
				this.writeInt((int)value);
				return;
			} else {				
				int output = Integer.reverseBytes((int)value);
				this.writeInt(output);
			}
		} else {
			if (isBigEndian) {
				int output = (int)(value & 0xffffffffL);
				this.writeInt(output);
			} else {
				int output = (int)(value & 0xffffffffL);
				output = Integer.reverseBytes(output);
				this.writeInt(output);
			}
		}
	}
}

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.