我們知道要隨機讀取檔案時 ,可以使用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()得到的流讀取時可能會讀取不完整(通常一個比較大的檔案,每次只會讀出一部分),導致資料處理失敗,我讀取遊戲資源時就遇到這個問題,找了很久才知道是流沒完整引起的。