在Java中流的一系列操做,可能会感到既熟悉又陌生。熟悉是由于很基础且出镜率很高,陌生对大多数程序员平时工做中不多写相关的代码。java
~~ 我是不多写~~程序员
回归正题,本章我不不是探讨流,主要来讲下形成‘标题’问题的缘由。数组
问题很简单,稍微看下源码或者debug下就能够找到问题所在,这是一些细节问题,既然出现了在此作下记录,给本身一个警戒。微信
今天微信上忽然收到前同事一段这样的问题描述测试
在读取文件时若是文件为空、致使进入while死循环,this
并附上一段代码。debug
/** * 将文件数据流写入到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; } } } }
咋一看这段代码也没啥问题!~是否是~code
咱们一点点的来分析下orm
首先陷入while死循环的条件bInStream.read(buffer)) != -1
ip
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 温故。
若有分析的错误的地方、欢迎指正