内容简介:在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的几个方法吧!
方法摘要
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[]) 造成死循环》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 再谈spring的循环依赖是怎么造成的?
- Class.forName 造成的线程阻塞
- 物联网黑客造成的经济损失有多少?
- 是什么造成了数据库的卡顿
- 一次断电造成ingress"问题" 原 荐
- 是什么造成了数据库的卡顿
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Egret——HTML5游戏开发指南
张鑫磊 等 / 电子工业出版社 / 2016-3 / 85
《Egret——HTML5游戏开发指南》由浅入深,在讲解游戏开发基础的同时提供众多实战案例供读者学习。《Egret——HTML5游戏开发指南》章节内容包含Egret基础概念及基础图形图像处理方法、网络相关操作、移动设备适配、性能优化、文本动画相关知识、调试技巧、DragonBones骨骼动画系统和P2物理引擎等。通过《Egret——HTML5游戏开发指南》,读者可以了解并掌握HTML5游戏开发技能......一起来看看 《Egret——HTML5游戏开发指南》 这本书的介绍吧!