我们知道要随机读取文件时 ,可以使用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();
}
}
* 可跳到指定位置的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 ..
}
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()得到的流读取时可能会读取不完整(通常一个比较大的文件,每次只会读出一部分),导致数据处理失败,我读取游戏资源时就遇到这个问题,找了很久才知道是流没完整引起的。