Jre的bug之一:文件处理中的字节数组读写ByteOutputStream

来源:互联网 发布:python 灰度图转rgb 编辑:程序博客网 时间:2024/06/17 12:03
在将文件以字节流的方式读到内存时,发现ByteOutputStream(com.sun.xml.internal.messaging.saaj.util.ByteOutputStream(),存在bug。
/** *  * 功能说明:读取指定路径文件为字节数组 * @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 blocke.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。

0 0