日期:2014-05-16 浏览次数:21144 次
优化BufferedRandomAccessFile。
?
优化原则:
这里举一典型的例子:
?
public void seek(long pos) throws IOException { ... this.bufstartpos = pos * bufbitlen / bufbitlen; // bufbitlen指buf[]的位长,例:若bufsize=1024,则bufbitlen=10。 ... }?
seek函数使用在各函数中,调用非常频繁,上面加重的这行语句根据pos和bufsize确定buf[]对应当前文件的映射位置,用"*"、"/"确定,显然不是一个好方法。
?
两者效率都比原来好,但后者显然更好,因为前者需要两次移位运算、后者只需一次逻辑与运算(bufmask可以预先得出)。
至此优化基本实现,逐字节COPY一个12兆的文件,(这里牵涉到读和写,结合缓冲读,用优化后BufferedRandomAccessFile试一下读/写的速度):
?
读 | 写 | 耗用时间(秒) |
RandomAccessFile | RandomAccessFile | 95.848 |
BufferedInputStream + DataInputStream | BufferedOutputStream + DataOutputStream | 2.935 |
BufferedRandomAccessFile | BufferedOutputStream + DataOutputStream | 2.813 |
BufferedRandomAccessFile | BufferedRandomAccessFile | 2.453 |
BufferedRandomAccessFile优 | BufferedRandomAccessFile优 | 2.197 |
?
可见优化尽管不明显,还是比未优化前快了一些,也许这种效果在老式机上会更明显。
以上比较的是顺序存取,即使是随机存取,在绝大多数情况下也不止一个BYTE,所以缓冲机制依然有效。而一般的顺序存取类要实现随机存取就不怎么容易了。
需要完善的地方
?
提供文件追加功能:
?
public boolean append(byte bw) throws IOException { return this.write(bw, this.fileendpos + 1); }
?
提供文件当前位置修改功能:
?
public boolean write(byte bw) throws IOException { return this.write(bw, this.curpos); }
?
返回文件长度(由于BUF读写的原因,与原来的RandomAccessFile类有所不同):
?
public long length() throws IOException { return this.max(this.fileendpos + 1, this.initfilelen); }
?
返回文件当前指针(由于是通过BUF读写的原因,与原来的RandomAccessFile类有所不同):
?
public long getFilePointer() throws IOException { return this.curpos; }
?
提供对当前位置的多个字节的缓冲写功能:
?
public void write(byte b[], int off, int len) throws IOException { long writeendpos = this.curpos + len - 1; if (writeendpos <= this.bufendpos) { // b[] in cur buf System.arraycopy(b, off, this.buf, (int)(this.curpos - this.bufstartpos), len); this.bufdirty = true; this.bufusedsize = (int)(writeendpos - this.bufstartpos + 1); } else { // b[] not in cur buf super.seek(this.curpos); super.write(b, off, len); } if (writeendpos > this.fileendpos) this.fileendpos = writeendpos; this.seek(writeendpos+1); } public void write(byte b[]) throws IOException { this.write(b, 0, b.length); }
?
提供对当前位置的多个字节的缓冲读功能:
?
public int read(byte b[], int off, int len) throws IOException { long readendpos = this.curpos + len - 1; if (readendpos <= this.bufendpos && readendpos <= this.fileendpos ) { // read in buf System.arraycopy(this.buf, (int)(this.curpos - this.bufstartpos), b, off, len); } else { // read b[] size > buf[] if (readendpos > this.fileendpos) { // read b[] part in file len = (int)(this.length() - this.curpos + 1); } super.seek(this.curpos); len = super.read(b, off, len); readendpos = this.curpos + len - 1; } this.seek(readendpos + 1); retu