踩坑笔记 >> InputStream.read(byte[]) 造成死循环

栏目: IT资讯 · 发布时间: 6年前

内容简介:在Java中流的一系列操作,可能会感到既熟悉又陌生。熟悉是因为很基础且出镜率很高,陌生对大多数程序员平时工作中很少写相关的代码。~~ 我是很少写~~回归正题,本章我不不是探讨流,主要来说下造成‘标题’问题的原因。

写在前面

Java 中流的一系列操作,可能会感到既熟悉又陌生。熟悉是因为很基础且出镜率很高,陌生对大多数 程序员 平时工作中很少写相关的代码。

~~ 我是很少写~~

回归正题,本章我不不是探讨流,主要来说下造成‘标题’问题的原因。

问题很简单,稍微看下源码或者debug下就可以找到问题所在,这是一些细节问题,既然出现了在此做下记录,给自己一个警惕。

场景引入

今天微信上突然收到前同事一段这样的问题描述

在读取文件时如果文件为空、导致进入while死循环,

并附上一段代码。

/**
     * 将文件数据流写入到zip流中
     * 
     * @param fileName
     * @param inputStream
     * @param outputStream
     * @throws IOException
     */
    public static void zipInputStream(String fileName, InputStream inputStream, ZipOutputStream outputStream)
            throws IOException {
        try {
            BufferedInputStream bInStream = new BufferedInputStream(inputStream);
            outputStream.putNextEntry(new ZipEntry(fileName));
            byte[] buffer = new byte[inputStream.available()];
            int r = 0;
            while ((r = bInStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, r);
            }
            outputStream.closeEntry();
        } catch (IOException e) {
            throw e;
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw e;
                }
            }
        }
    }

咋一看这段代码也没啥问题!

我们一点点的来分析下

首先陷入while死循环的条件 bInStream.read(buffer)) != -1

while ((r = bInStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, r);
}

看下源码中的描述,

/**
     * Reads up to <code>len</code> bytes of data from this input stream
     * into an array of bytes. If <code>len</code> is not zero, the method
     * blocks until some input is available; otherwise, no
     * bytes are read and <code>0</code> is returned.
     * <p>
     * This method simply performs <code>in.read(b, off, len)</code>
     * and returns the result.
     *
     * @param      b     the buffer into which the data is read.
     * @param      off   the start offset in the destination array <code>b</code>
     * @param      len   the maximum number of bytes read.
     * @return     the total number of bytes read into the buffer, or
     *             <code>-1</code> if there is no more data because the end of
     *             the stream has been reached.
     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
     * <code>len</code> is negative, or <code>len</code> is greater than
     * <code>b.length - off</code>
     * @exception  IOException  if an I/O error occurs.
     * @see        java.io.FilterInputStream#in
     */
    public int read(byte b[], int off, int len) throws IOException {
        return in.read(b, off, len);
    }

上面描述有这么一段,如果byte[]数组的len为0则不做任何操作直接返回0。

看到这问题基本就可以定位了,在看代码中byte[]的定义。

byte[] buffer = new byte[inputStream.available()];

看到这小伙们就笑了 inputStream.available() ,你读的是一个空文件可不是为0。

/**
     * Returns an estimate of the number of bytes that can be read (or
     * skipped over) from this input stream without blocking by the next
     * caller of a method for this input stream. The next caller might be
     * the same thread or another thread.  A single read or skip of this
     * many bytes will not block, but may read or skip fewer bytes.
     * <p>
     * This method returns the result of {@link #in in}.available().
     *
     * @return     an estimate of the number of bytes that can be read (or skipped
     *             over) from this input stream without blocking.
     * @exception  IOException  if an I/O error occurs.
     */
    public int available() throws IOException {
        return in.available();
    }

描述的很清楚,返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

说到这基本就反应过来,再说就有点啰嗦了。

总结

像这种问题其实和技术和能力没多大关系、主要是细心和经验。其实定义一个程序员的牛逼与否在于他踩过的坑是否足够多。

既然说到这那就顺便温故下InputStream的几个方法吧!

方法摘要

int available() : 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

void close() :关闭此输入流并释放与该流关联的所有系统资源。

void mark(int readlimit):在此输入流中标记当前的位置。

boolean markSupported() :测试此输入流是否支持 mark 和 reset 方法。

abstract int read() :测试此输入流是否支持 mark 和 reset 方法。

int read(byte[] b) :从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

int read(byte[] b, int off, int len) :将输入流中最多 len 个数据字节读入 byte 数组。

void reset() :将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

long skip(long n) :跳过和丢弃此输入流中数据的 n 个字节。

以次简单的问题来对InputStream 温故。

如有分析的错误的地方、欢迎指正


以上所述就是小编给大家介绍的《踩坑笔记 >> InputStream.read(byte[]) 造成死循环》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Types and Programming Languages

Types and Programming Languages

Benjamin C. Pierce / The MIT Press / 2002-2-1 / USD 95.00

A type system is a syntactic method for automatically checking the absence of certain erroneous behaviors by classifying program phrases according to the kinds of values they compute. The study of typ......一起来看看 《Types and Programming Languages》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

SHA 加密
SHA 加密

SHA 加密工具