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

在将文件以字节流的方式读到内存时,发现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 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。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值