ByteBuffer.get() 与 InputStream.read()

在使用 ByteBuffer 替换 InputStream 时,遇到了一个问题,就是 InputStream 的 read 方法与 ByteBuffer 的 get 方法是不一样的,在遇到小于 0 的 byte 就会出错。

InputStream 的 read() 方法读取一个 byte,返回一个无符号数,范围 0~255

	/**
     * Reads the next byte of data from the input stream. The value byte is
     * returned as an <code>int</code> in the range <code>0</code> to
     * <code>255</code>. If no byte is available because the end of the stream
     * has been reached, the value <code>-1</code> is returned. 
     */
    public abstract int read() throws IOException;


ByteBuffer 的 get() 方法读取一个 byte,返回一个有符号数,范围 -128-127

 /**
     * Relative <i>get</i> method.  Reads the byte at this buffer's
     * current position, and then increments the position.
     *
     * @return  The byte at the buffer's current position
     *
     * @throws  BufferUnderflowException
     *          If the buffer's current position is not smaller than its limit
     */
    public abstract byte get();


byte 的范围是 -128 ~ 127。也就是 new 一个 byte 的时候只能赋值这个范围。
下面这里凡是小于 0 的 byte,两个的输出就不一样

		byte[] bytes = new byte[1];
		bytes[0] = 127;
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        int a = inputStream.read();
        System.out.println(a);

        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        int b = buffer.get();
        System.out.println(b);


因为 InputStream 在读的时候与了一个 0xFF,下面是 ByteArrayInputStream 的:

public synchronized int read() {
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }
    

而 ByteBuffer 在读的时候并没有 与 0xFF。可以将 ByteBuffer 的 get 得到的数字 & 0xFF,来得到 InputStream 的 read 的效果:

以 byte = -13 为例,InputStream 的 read 返回 243,ByteBuffer 的 get 返回 -13。下面就是这个返回的 int 的各个 bit

243: 0000000011110011
-13: 1111111111110011
0xFF:0000000011111111
-13 & 0 xFF: 0000000011110011
这段代码中可以进行以下优化: 1. 对于文件读取和写入操作,可以使用NIO库中的Channels和Buffers来进行优化,可以提高读写速度和效率。 2. 对于InputStream的关闭操作,可以使用try-with-resources语句来简化代码和避免资源泄漏。 3. 在进行文件操作前,可以先对文件进行缓存,减少重复读写。 4. 对于异常处理,最好不要使用printStackTrace()方法,而是应该记录错误日志或者抛出自定义异常。 优化后的代码如下: ```java try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream()); ReadableByteChannel inChannel = Channels.newChannel(inputStream); ) { ByteBuffer buffer = ByteBuffer.allocate(1024); for (Map<String, String> iUrl : dbUrls) { for (Map.Entry<String, String> map : iUrl.entrySet()) { //检查是否有同名文件 String fileName = checkFileName(urlList, map.getKey()); URL url = new URL(map.getValue()); zipOut.putNextEntry(new ZipEntry(fileName)); //将文件名放入list,检查是否同名 urlList.add(map.getKey()); try (InputStream inputStream = url.openStream(); ReadableByteChannel urlChannel = Channels.newChannel(inputStream); ) { while (urlChannel.read(buffer) != -1) { buffer.flip(); zipOut.write(buffer.array(), 0, buffer.limit()); buffer.clear(); } } catch (IOException e) { throw new Exception("导出压缩包失败"); } zipOut.closeEntry();// 关闭入口 } } zipOut.flush(); } catch (IOException e) { throw new Exception("导出压缩包失败"); } ``` 注意,以上代码仅供参考,优化方案需要根据实际情况进行调整。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值