Code example for RandomAccessFile

Methods: getFilePointer, length, seek, setLength, write

0
			this.indexSize = getIntAt(INDEX_SIZE_OFFSET);
		} 
	} 
 
	public void initIfEmpty(int indexSize, int fileSize) throws IOException {
		if( this.raf.length() <= HEADER_LENGTH ) {
			this.indexSize = indexSize;
			if( !writeMode ) throw new IOException("Can't initialize unless in write mode");
			this.raf.setLength(fileSize);
			Chunk indexChunk = new Chunk();
			indexChunk.offset = INDEX_CHUNK_OFFSET;
			indexChunk.type = CHUNK_TYPE_INDX;
			writeChunk(indexChunk, createIndexData(indexSize));
			Chunk eofChunk = writeEofChunk(indexChunk.offset);
			setLastChunkOffset(eofChunk.offset);
		} 
	} 
	 
	public void close() throws IOException { 
		this.raf.close();
	} 
	 
	//// Accessors //// 
	 
	public File getFile() {
		return file;
	} 
	 
	public boolean isWritable() { 
		return writeMode;
	} 
	 
	//// Int r/w functions //// 
	 
	static void intToBytes(int i, byte[] b, int offset) {
		b[offset+0] = (byte)((i >> 24) & 0xFF);
		b[offset+1] = (byte)((i >> 16) & 0xFF);
		b[offset+2] = (byte)((i >>  8) & 0xFF);
		b[offset+3] = (byte)((i >>  0) & 0xFF);
	} 
	 
	static byte[] intToBytes(int i) {
		byte[] bytes = new byte[4];
		intToBytes(i, bytes, 0);
		return bytes;
	} 
	 
	static int bytesToInt(byte[] b, int offset) {
		return 
			((b[offset+0] << 24) & 0xFF000000) |
			((b[offset+1] << 16) & 0x00FF0000) |
			((b[offset+2] <<  8) & 0x0000FF00) |
			((b[offset+3] <<  0) & 0x000000FF);
	} 
	 
	public static int strToInt(String c) {
		try { 
			return bytesToInt(c.getBytes("UTF-8"), 0);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		} 
	} 
	 
	public static String intToStr(int i) {
		try { 
			return new String(intToBytes(i), "UTF-8");
		} catch( UnsupportedEncodingException e ) {
			throw new RuntimeException(e);
		} 
	} 
	 
	protected int readInt() throws IOException { 
		return bytesToInt(readBytes(4, "readInt"), 0); 
	} 
	 
	protected void writeInt(int value) throws IOException {
		byte[] b = new byte[4];
		intToBytes(value, b, 0);
		raf.write(b);
	} 
	 
	protected int getIntAt(int offset) throws IOException {
		raf.seek(offset);
		return readInt(); 
	} 
	 
	protected void setIntAt(int offset, int value) throws IOException {
		raf.seek(offset);
		writeInt(value);
	} 
	 
	protected byte[] readBytes(int count, String context) throws IOException {
		byte[] data = new byte[count];
		raf.readFully(data);
		return data;
	} 
	 
	public byte[] getBytes(int offset, int count) throws IOException {
		raf.seek(offset);
		return readBytes(count, "getBytes");
	} 
	 
	//// Edit the index //// 
	 
	public int getRawIndexItem(int itemNum) throws IOException {
		return getIntAt(INDEX_ITEMS_OFFSET + itemNum*4);
	} 
	 
	public int getIndexItemOffset(int itemNum) {
		return INDEX_ITEMS_OFFSET + (RESERVED_INDEX_ITEMS+itemNum)*4;
	} 
	 
	public int getIndexItem(int itemNum) throws IOException {
		if( itemNum < 0 || itemNum >= indexSize ) throw new IOException("Index " + itemNum + " out of range: 0..."+indexSize);
		return getRawIndexItem(itemNum + RESERVED_INDEX_ITEMS);
	} 
	 
	public int getCheckedIndexItem(int itemNum) throws IOException {
		int offset = getIndexItem(itemNum);
		return checkIndexPointer(offset, itemNum);
	} 
 
	public void setRawIndexItem(int itemNum, int value) throws IOException {
		setIntAt(INDEX_ITEMS_OFFSET + itemNum*4, value);
	} 
 
	public void setIndexItem(int itemNum, int value) throws IOException {
		if( itemNum < 0 || itemNum >= indexSize ) throw new IOException("Index " + itemNum + " out of range: 0..."+indexSize);
		setRawIndexItem(itemNum + RESERVED_INDEX_ITEMS, value);
	} 
	 
	protected void setLastChunkOffset(int offset) throws IOException {
		setRawIndexItem(ENDF_LIST_INDEX, offset);
	} 
	 
	public int getIndexRawItemCount( Chunk indexChunk ) throws IOException {
		return getIntAt( indexChunk.offset + CHUNK_HEADER_LENGTH );
	} 
	public int[] getIndexItems( Chunk indexChunk ) throws IOException {
		int itemCount = getIndexRawItemCount( indexChunk );
		int[] items = new int[itemCount];
		for( int i=0; i<itemCount; ++i ) {
			items[i] = readInt();
		} 
		return items;
	} 
 
	//// Check / correct pointers //// 
	 
	protected boolean isPointerOk( int pointer ) throws IOException {
		return pointer >= HEADER_LENGTH && pointer < raf.length() - CHUNK_HEADER_LENGTH;
	} 
	 
	protected int checkIndexPointer( int pointer, int index ) throws IOException {
		if( pointer == 0 ) return 0;
		if( !isPointerOk(pointer) ) {
			throw new IOException("Bad index pointer at " + intToHex(getIndexItemOffset(index)) +
					" (index " + index + "): " + intToHex(pointer));
		} 
		return pointer;
	} 
	 
	protected void checkPointer( int pointer, int pointerOffset ) throws IOException {
		if( !isPointerOk(pointer) ) {
			throw new IOException("Pointer at " + pointerOffset + " is bad, points to " + pointer );
		} 
	} 
	 
	//// Load chunk //// 
	 
	public Chunk getChunk(int offset) throws IOException {
		if( offset == 0 ) return null;
		raf.seek(offset);
		byte[] header = readBytes(CHUNK_HEADER_LENGTH, "chunk header");
		Chunk chunk = new Chunk();
		chunk.offset = offset;
		int magic = bytesToInt(header, CHUNK_MAGIC_OFFSET); 
		if( magic != CHUNK_MAGIC ) {
			throw new IOException("Read malformed chunk at " + intToHex(offset) + " (bad magic: " + intToHex(magic));
		} 
		chunk.prevOffset     = bytesToInt(header, CHUNK_PREV_OFFSET);
		chunk.nextOffset     = bytesToInt(header, CHUNK_NEXT_OFFSET);
		chunk.listPrevOffset = bytesToInt(header, CHUNK_LIST_PREV_OFFSET);
		chunk.listNextOffset = bytesToInt(header, CHUNK_LIST_NEXT_OFFSET);
		chunk.type           = bytesToInt(header, CHUNK_TYPE_OFFSET);
		return chunk;
	} 
	 
	public byte[] getChunkData(Chunk c) throws IOException {
		int start = c.offset + CHUNK_HEADER_LENGTH;
		int length = (c.nextOffset == 0) ? 0 : c.nextOffset - start;
		return getBytes(start,length);
	} 
 
	//// Write a brand new chunk //// 
	 
	protected void writeChunk(Chunk chunk, byte[] data) throws IOException {
		raf.seek(chunk.offset);
		byte[] chunkHeader = new byte[CHUNK_HEADER_LENGTH];
		intToBytes(CHUNK_MAGIC,          chunkHeader, CHUNK_MAGIC_OFFSET);
		intToBytes(chunk.prevOffset,     chunkHeader, CHUNK_PREV_OFFSET);
		intToBytes(chunk.nextOffset,     chunkHeader, CHUNK_NEXT_OFFSET);
		intToBytes(chunk.listPrevOffset, chunkHeader, CHUNK_LIST_PREV_OFFSET);
		intToBytes(chunk.listNextOffset, chunkHeader, CHUNK_LIST_NEXT_OFFSET);
		intToBytes(chunk.type,           chunkHeader, CHUNK_TYPE_OFFSET);
		raf.write(chunkHeader);
		if( data != null ) raf.write(data);
	} 
	 
	protected Chunk writeEofChunk(int prevOffset) throws IOException {
		Chunk eofChunk = new Chunk();
		eofChunk.offset = (int)raf.getFilePointer();
		eofChunk.prevOffset = prevOffset;
		eofChunk.type = CHUNK_TYPE_ENDF;
		writeChunk(eofChunk, null);
		if( prevOffset != 0 ) setChunkNext(prevOffset, eofChunk.offset);
		return eofChunk;