/** * */ package com.github.seanlinwang.fkv; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; /** * @author sean.wang * @since Nov 16, 2011 */ public class FkvFileStore implements FkvStore { private RandomAccessFile in; private FileChannel ch; private MappedByteBuffer buffer; private final static int DEFAULT_DB_SIZE = 1024 * 1024; private boolean needDeserial = false; public FkvFileStore(File dbFile) throws IOException { this(dbFile, 0); } public FkvFileStore(File dbFile, int dbSize) throws IOException { if (!dbFile.exists()) { dbFile.createNewFile(); } in = new RandomAccessFile(dbFile, "rw"); ch = in.getChannel(); long mappedSize = dbFile.length(); if (mappedSize <= 0) { if (dbSize <= 0) { mappedSize = DEFAULT_DB_SIZE; } else { mappedSize = dbSize; } } else { this.needDeserial = true; } //文件提供了内存的持久化方式,否则内存中的数据一旦丢失,则数据无法恢复 buffer = ch.map(FileChannel.MapMode.READ_WRITE, 0, mappedSize); } @Override public void close() throws IOException { ch.close(); in.close(); } @Override public void get(byte[] bytes) { this.buffer.get(bytes); } // 对于文件而言, 获取出的数据都是二进制的字节数组! 客户端实现类要自己将二进制转换成自定义对象 @Override public byte[] get(int startIndex, int size) { byte[] value = new byte[size]; buffer.position(startIndex); buffer.get(value); return value; } @Override public ByteBuffer getBuffer() { return this.buffer; } @Override public boolean isNeedDeserial() { return needDeserial; } @Override public void put(int startIndex, byte value) { buffer.position(startIndex); buffer.put(value); } @Override public void put(int startIndex, byte[] value) { buffer.position(startIndex); buffer.put(value); } @Override public int remaining() { return this.buffer.remaining(); } @Override public void rewind() { this.buffer.rewind(); } }