博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BufferedRandomAccessFile的实现
阅读量:6464 次
发布时间:2019-06-23

本文共 10805 字,大约阅读时间需要 36 分钟。

java import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.util.Arrays;public class BufferedRandomAccessFile extends RandomAccessFile {    static final int LogBuffSz_ = 16; // 64K buffer    public static final int BuffSz_ = (1 << LogBuffSz_);    static final long BuffMask_ = ~(((long) BuffSz_) - 1L);    private String path_;    /*     * This implementation is based on the buffer implementation in Modula-3's     * "Rd", "Wr", "RdClass", and "WrClass" interfaces.     */    private boolean dirty_; // true iff unflushed bytes exist    private boolean syncNeeded_; // dirty_ can be cleared by e.g. seek, so track sync separately    private long curr_; // current position in file    private long lo_, hi_; // bounds on characters in "buff"    private byte[] buff_; // local buffer    private long maxHi_; // this.lo + this.buff.length    private boolean hitEOF_; // buffer contains last file block?    private long diskPos_; // disk position      /*      * To describe the above fields, we introduce the following abstractions for      * the file "f":      *      * len(f) the length of the file curr(f) the current position in the file      * c(f) the abstract contents of the file disk(f) the contents of f's      * backing disk file closed(f) true iff the file is closed      *      * "curr(f)" is an index in the closed interval [0, len(f)]. "c(f)" is a      * character sequence of length "len(f)". "c(f)" and "disk(f)" may differ if      * "c(f)" contains unflushed writes not reflected in "disk(f)". The flush      * operation has the effect of making "disk(f)" identical to "c(f)".      *      * A file is said to be *valid* if the following conditions hold:      *      * V1. The "closed" and "curr" fields are correct:      *      * f.closed == closed(f) f.curr == curr(f)      *      * V2. The current position is either contained in the buffer, or just past      * the buffer:      *      * f.lo <= f.curr <= f.hi      *      * V3. Any (possibly) unflushed characters are stored in "f.buff":      *      * (forall i in [f.lo, f.curr): c(f)[i] == f.buff[i - f.lo])      *      * V4. For all characters not covered by V3, c(f) and disk(f) agree:      *      * (forall i in [f.lo, len(f)): i not in [f.lo, f.curr) => c(f)[i] ==      * disk(f)[i])      *      * V5. "f.dirty" is true iff the buffer contains bytes that should be      * flushed to the file; by V3 and V4, only part of the buffer can be dirty.      *      * f.dirty == (exists i in [f.lo, f.curr): c(f)[i] != f.buff[i - f.lo])      *      * V6. this.maxHi == this.lo + this.buff.length      *      * Note that "f.buff" can be "null" in a valid file, since the range of      * characters in V3 is empty when "f.lo == f.curr".      *      * A file is said to be *ready* if the buffer contains the current position,      * i.e., when:      *      * R1. !f.closed && f.buff != null && f.lo <= f.curr && f.curr < f.hi      *      * When a file is ready, reading or writing a single byte can be performed      * by reading or writing the in-memory buffer without performing a disk      * operation.      */    /**     * Open a new BufferedRandomAccessFile on file     * in mode mode, which should be "r" for reading only, or     * "rw" for reading and writing.     */    public BufferedRandomAccessFile(File file, String mode) throws IOException {        this(file, mode, 0);    }    public BufferedRandomAccessFile(File file, String mode, int size) throws IOException {        super(file, mode);        path_ = file.getAbsolutePath();        this.init(size);    }    /**     * Open a new BufferedRandomAccessFile on the file named     * name in mode mode, which should be "r" for     * reading only, or "rw" for reading and writing.     */    public BufferedRandomAccessFile(String name, String mode) throws IOException {        this(name, mode, 0);    }    public BufferedRandomAccessFile(String name, String mode, int size) throws FileNotFoundException {        super(name, mode);        path_ = name;        this.init(size);    }    private void init(int size) {        this.dirty_ = false;        this.lo_ = this.curr_ = this.hi_ = 0;        this.buff_ = (size > BuffSz_) ? new byte[size] : new byte[BuffSz_];        this.maxHi_ = (long) BuffSz_;        this.hitEOF_ = false;        this.diskPos_ = 0L;    }    public String getPath() {        return path_;    }    public void sync() throws IOException {        if (syncNeeded_) {            flush();            getChannel().force(true);            syncNeeded_ = false;        }    }//      public boolean isEOF() throws IOException//      {//          assert getFilePointer() <= length();//          return getFilePointer() == length();//      }    public void close() throws IOException {        this.flush();        this.buff_ = null;        super.close();    }    /**     * Flush any bytes in the file's buffer that have not yet been written to     * disk. If the file was created read-only, this method is a no-op.     */    public void flush() throws IOException {        this.flushBuffer();    }    /* Flush any dirty bytes in the buffer to disk. */    private void flushBuffer() throws IOException {        if (this.dirty_) {            if (this.diskPos_ != this.lo_)                super.seek(this.lo_);            int len = (int) (this.curr_ - this.lo_);            super.write(this.buff_, 0, len);            this.diskPos_ = this.curr_;            this.dirty_ = false;        }    }    /*     * Read at most "this.buff.length" bytes into "this.buff", returning the     * number of bytes read. If the return result is less than     * "this.buff.length", then EOF was read.     */    private int fillBuffer() throws IOException {        int cnt = 0;        int rem = this.buff_.length;        while (rem > 0) {            int n = super.read(this.buff_, cnt, rem);            if (n < 0)                break;            cnt += n;            rem -= n;        }        if ((cnt < 0) && (this.hitEOF_ = (cnt < this.buff_.length))) {            // make sure buffer that wasn't read is initialized with -1            Arrays.fill(this.buff_, cnt, this.buff_.length, (byte) 0xff);        }        this.diskPos_ += cnt;        return cnt;    }    /*     * This method positions this.curr at position pos.     * If pos does not fall in the current buffer, it flushes the     * current buffer and loads the correct one.

* * On exit from this routine this.curr == this.hi iff pos * is at or past the end-of-file, which can only happen if the file was * opened in read-only mode. */ public void seek(long pos) throws IOException { if (pos >= this.hi_ || pos < this.lo_) { // seeking outside of current buffer -- flush and read this.flushBuffer(); this.lo_ = pos & BuffMask_; // start at BuffSz boundary this.maxHi_ = this.lo_ + (long) this.buff_.length; if (this.diskPos_ != this.lo_) { super.seek(this.lo_); this.diskPos_ = this.lo_; } int n = this.fillBuffer(); this.hi_ = this.lo_ + (long) n; } else { // seeking inside current buffer -- no read required if (pos < this.curr_) { // if seeking backwards, we must flush to maintain V4 this.flushBuffer(); } } this.curr_ = pos; } public long getFilePointer() { return this.curr_; } public long length() throws IOException { // max accounts for the case where we have written past the old file length, but not yet flushed our buffer return Math.max(this.curr_, super.length()); } public int read() throws IOException { if (this.curr_ >= this.hi_) { // test for EOF // if (this.hi < this.maxHi) return -1; if (this.hitEOF_) return -1; // slow path -- read another buffer this.seek(this.curr_); if (this.curr_ == this.hi_) return -1; } byte res = this.buff_[(int) (this.curr_ - this.lo_)]; this.curr_++; return ((int) res) & 0xFF; // convert byte -> int } public int read(byte[] b) throws IOException { return this.read(b, 0, b.length); } public int read(byte[] b, int off, int len) throws IOException { if (this.curr_ >= this.hi_) { // test for EOF // if (this.hi < this.maxHi) return -1; if (this.hitEOF_) return -1; // slow path -- read another buffer this.seek(this.curr_); if (this.curr_ == this.hi_) return -1; } len = Math.min(len, (int) (this.hi_ - this.curr_)); int buffOff = (int) (this.curr_ - this.lo_); System.arraycopy(this.buff_, buffOff, b, off, len); this.curr_ += len; return len; } public void write(int b) throws IOException { if (this.curr_ >= this.hi_) { if (this.hitEOF_ && this.hi_ < this.maxHi_) { // at EOF -- bump "hi" this.hi_++; } else { // slow path -- write current buffer; read next one this.seek(this.curr_); if (this.curr_ == this.hi_) { // appending to EOF -- bump "hi" this.hi_++; } } } this.buff_[(int) (this.curr_ - this.lo_)] = (byte) b; this.curr_++; this.dirty_ = true; syncNeeded_ = true; } public void write(byte[] b) throws IOException { this.write(b, 0, b.length); } public void write(byte[] b, int off, int len) throws IOException { while (len > 0) { int n = this.writeAtMost(b, off, len); off += n; len -= n; this.dirty_ = true; syncNeeded_ = true; } } /* * Write at most "len" bytes to "b" starting at position "off", and return * the number of bytes written. */ private int writeAtMost(byte[] b, int off, int len) throws IOException { if (this.curr_ >= this.hi_) { if (this.hitEOF_ && this.hi_ < this.maxHi_) { // at EOF -- bump "hi" this.hi_ = this.maxHi_; } else { // slow path -- write current buffer; read next one this.seek(this.curr_); if (this.curr_ == this.hi_) { // appending to EOF -- bump "hi" this.hi_ = this.maxHi_; } } } len = Math.min(len, (int) (this.hi_ - this.curr_)); int buffOff = (int) (this.curr_ - this.lo_); System.arraycopy(b, off, this.buff_, buffOff, len); this.curr_ += len; return len; }}

转载地址:http://anezo.baihongyu.com/

你可能感兴趣的文章
子程序框架
查看>>
多维数组元素的地址
查看>>
数据库运维体系_SZMSD
查看>>
aspose 模板输出
查看>>
福大软工1816 · 第三次作业 - 结对项目1
查看>>
selenium多个窗口切换
查看>>
《单页面应用》所获知识点
查看>>
静态库 调试版本 和发布版本
查看>>
读书笔记四
查看>>
JAVA中的finalize()方法
查看>>
慕课网学习手记--炫丽的倒计时效果Canvas绘图与动画基础
查看>>
==与equals()的区别
查看>>
基本分类方法——KNN(K近邻)算法
查看>>
在XenCenter6.2中构建CentOS7虚拟机的启动错误
查看>>
.NET Framework3.0/3.5/4.0/4.5新增功能摘要
查看>>
php中表单提交复选框与下拉列表项
查看>>
熟悉常用的Linux操作
查看>>
WordPress 前端投稿/编辑发表文章插件 DJD Site Post(支持游客和已注册用户)汉化版 免费下载...
查看>>
C# 自定义事件整理项目 - EventDemo
查看>>
面象过程与面象对象
查看>>