在将文件以字节流的方式读到内存时,发现ByteOutputStream(com.sun.xml.internal.messaging.saaj.util.ByteOutputStream(),存在bug。
ByteOutputStream.toByteArray()相关部分:
造成这个问题的原因,在于数据的不一致性:count所代表的真实数据的长度和分配空间得到的buf数组的长度,不一样。
/**
*
* 功能说明:读取指定路径文件为字节数组
* @param classPath
* @return byte[]
* @time:2016年9月20日下午11:42:58
* @author:linghushaoxia
* @exception:
*
*/
public static byte[] readBytes(String filePath){
//返回结果
byte[] result = null;
BufferedInputStream inputStream = null;
ByteOutputStream outputStream=null;
try {
inputStream=new BufferedInputStream(new FileInputStream(filePath));
outputStream= new ByteOutputStream();
int bufferSize=1024;
byte[] buffer=new byte[bufferSize];
while(inputStream.available()>0){
//还未读取的字节个数
int ava = inputStream.available();
if(ava<bufferSize){
bufferSize=ava;
}
inputStream.read(buffer, 0, bufferSize);
outputStream.write(buffer, 0, bufferSize);
}
//存在问题
result = outputStream.getBytes();
//正确,官方不建议使用
byte[] byteArray=outputStream.toByteArray();
//更好一些的解决办法,使用ByteArrayOutputStream
} catch (Exception e) {
e.printStackTrace();
}finally{
/**
* 关闭输入输出流
*/
if (inputStream!=null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (outputStream!=null) {
outputStream.close();
}
}
return result;
}
使用ByteOutputStream.getBytes()会得到包含空数据的字节流,当然和文件的真实数据就不相符了。
原因在于,ByteOutputStream.getBytes获取的数据包含扩大容量的初始字节;这里涉及到两个关键属性buf和count
buf:ByteOutputStream的字节缓冲区
count:实际字节的个数
ByteOutputStream.getBytes,直接返回buf,而buf包含扩容后得到的默认值字节
ByteOutputStream.toByteArray(),则是新建一个字节数组,只读取buf的一部分:count个长度,这是正确的。
关键代码如下
ByteOutputStream.getBytes()中涉及到buf的部分:
/**
* Ensure that the buffer has at least this much space.
*/
private void ensureCapacity(int space) {
int newcount = space + count;
if (newcount > buf.length) {
byte[] newbuf = new byte[Math.max(buf.length << 1, newcount)];
System.arraycopy(buf, 0, newbuf, 0, count);
buf = newbuf;
}
}
public void write(byte[] b, int off, int len) {
ensureCapacity(len);
System.arraycopy(b, off, buf, count, len);
count += len;
}
ByteOutputStream.toByteArray()相关部分:
/**
* Evil buffer reallocation method.
* Don't use it unless you absolutely have to.
*
* @deprecated
* because this is evil!
*/
public byte toByteArray()[] {
byte[] newbuf = new byte[count];
System.arraycopy(buf, 0, newbuf, 0, count);
return newbuf;
}
造成这个问题的原因,在于数据的不一致性:count所代表的真实数据的长度和分配空间得到的buf数组的长度,不一样。
可见,分配空间中存在一个必须要注意的问题,那就是维护实际数据长度和实际分配空间的关系。
测试环境:Oracle JDK1.7。