现在的位置: 首页 > 综合 > 正文

巧用ByteArrayInputStream进行快速随机定位访问

2013年09月11日 ⁄ 综合 ⁄ 共 1545字 ⁄ 字号 评论关闭

我们知道要随机读取文件时 ,可以使用RandomAcessFile,但要高率随机读取一个文件中的不同数据块时,这个类却不能满足我们的需要,因为它太慢了!!!

例如,做一个图像解码器,经常需要跳到不同地址读取不同的数据块,而不能只是使用流读取。

影响速度的问题在于读取太多次外存,于是想到一次将文件读到内存,但而找不到可以随机定位的流。。。难道非要用RandomAcessFile ??No!!

突然想起ByteArrayInputStream,它不是直接使用字节数组存储吗?观其代码,发现只需要略作修改即可满足需求:

 

/**
 * 可跳到指定位置的ByteArrayInputStrem<br>
 * seek(int pos)
 * 
 * 
@author Kylixs
 * @date
 
*/

public class SeekByteArrayInputStream extends ByteArrayInputStream {

    
public SeekByteArrayInputStream(byte[] buf) {
        
super(buf);
    }


    
public SeekByteArrayInputStream(byte[] buf, int offset, int length) {
        
super(buf, offset, length);
    }


    
public void seek(int pos) {
        
if (pos < 0 || pos > count) throw new IndexOutOfBoundsException("" + pos + ":" + count); }
        
// if(this.pos!=pos) {
        
// System.err.println("seek: "+(pos-this.pos)+", "+this.pos+"-"+pos);
        
// }
        this.pos = pos;
    }


    
public long getPosition() {
        
return pos;
    }


    
public void close() {
        buf 
= null;
        count 
= 0;
        System.gc();
    }


}

 

使用例子:

 

public void load(InputStream in) throws Exception{
    
byte[] buf = new byte[in.available()];
    
int a = 0, count = 0;
    
while (in.available() > 0{
        a 
= in.read(buf, count, in.available());
        count 
+= a;
    }

    
// construct a new seekable stream
    SeekByteArrayInputStream sIn = new SeekByteArrayInputStream(buf);
                     
// your code ..
}

这个方法去读取 jar包中的资源文件时特别有效,用getResourcesAsStream()得到的流读取时可能会读取不完整(通常一个比较大的文件,每次只会读出一部分),导致数据处理失败,我读取游戏资源时就遇到这个问题,找了很久才知道是流没完整引起的。

 

抱歉!评论已关闭.