Java InputStream的read(byte [])方法 [英] Java InputStream's read(byte[]) method

查看:117
本文介绍了Java InputStream的read(byte [])方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先是一些背景。
它不需要回答实际问题,但也许它会帮助我们正确看待问题。

First some background. Its not needed to answer the actual question, but maybe it'll help put things in perspective.

我用java编写了一个mp3库(h)它读出.mp3文件中存储在ID3标签中的信息。有关歌曲的信息,如歌曲名称,发行歌曲的CD,曲目编号等,都存储在.3文件开头的ID3标签中。

I have written an mp3 library in java (h) which reads out the information stored in the ID3 tag in an .mp3 file. Information about the song like the name of the song, the CD the song was released on, the track number, etc. are stored in this ID3 tag right at the beginning of an .mp3 file.

我在12,579个mp3文件上测试了这个库,这些文件位于我的本地硬盘上,它运行完美。没有一个IO错误。

I have tested the library on 12,579 mp3 files which are located on my local hard drive, and it works flawlessly. Not a single IO error.

当我执行mp3文件位于Web服务器上的同样的事情时,我收到IO错误。好吧,实际上并不是一个错误。实际上它是InputStream的read(byte [])方法行为的差异。

When I perform the same thing where the mp3 files are located on a web server, I get an IO error. Well, not actually an error. Actually its a difference in the behavior of the InputStream's read(byte[]) method.

下面的例子将说明我试图阅读时出现的问题来自mp3文件的图像文件(.jpg,.gif,.png等)。

The example below will illustrate the problem, which occurs when I'm trying to read an image file (.jpg, .gif, .png, etc) from the mp3 file.

// read bytes from an .mp3 file on your local hard drive
// reading from an input stream created this way works flawlessly
InputStream      inputStream = new FileInputStream("song.mp3");

// read bytes from an .mp3 file given by a url
// reading from an input stream created this way fails every time.
URL               url            = "http://localhost/song.mp3");
HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();
httpConnection.connect();
InputStream       inputStream    = url.openStream();


int    size         = 25000;            // size of the image file 
byte[] buffer       = new byte[size];
int    numBytesRead = inputStream.read(buffer);

if (numBytesRead != buffer.length)
   throw new IOException("Error reading the bytes into the buffer.  Expected " + buffer.length + " bytes but got " + numBytesRead + " bytes");

所以,我的观察是:
调用inputStream.read(buffer);当输入流是FileInputStream时,总是读取整个字节数。但是当我使用从http连接获得的输入流时,它只读取部分数量。

So, my observation is: Calling inputStream.read(buffer); always reads the entire number of bytes when the input stream is a FileInputStream. But it only reads a partial amount when I am using an input stream obtained from an http connection.

因此我的问题是:
一般情况下,我可以不要假设InputStream的read(byte [])方法将被阻塞,直到读取了整个字节数(或达到EOF)?
也就是说,我是否假设读取(byte [])方法的行为不正确,而且我很幸运使用FileInputStream?

And hence my question is: In general, can I not assume that the InputStream's read(byte[]) method will block until the entire number of bytes has been read (or EOF is reached)? That is, have I assumed behavior that is not true of the read(byte[]) method, and I've just gotten lucky working with FileInputStream?

InputStream.read(byte [])的正确和一般行为是否需要将调用置于循环中并继续读取字节,直到读取了所需的字节数或已达到EOF?类似下面的代码:

Is the correct, and general behavior of InputStream.read(byte[]) that I need to put the call in a loop and keep reading bytes until the desired number of bytes have been read, or EOF has been reached? Something like the code below:

int    size        = 25000;
byte[] buffer      = new byte[size];
int numBytesRead   = 0;
int totalBytesRead = 0;

while (totalBytesRead != size && numBytesRead != -1)
{
   numBytesRead    = inputStream.read(buffer);
   totalBytesRead += numBytesRead
}


推荐答案

您的结论是合理的,请查看 InputStream.read(byte [])

Your conclusions are sound, take a look at the documentation for InputStream.read(byte[]):

从输入流中读取一些字节数并将它们存储到缓冲区数组b的
中。实际读取的字节数以
整数形式返回。此方法将阻塞,直到输入数据可用,检测到
文件的结尾,或者抛出异常。

Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.

不保证 read(byte [])将填充您提供的数组,只是它将读取至少1个字节(假设您的数组长度> 0),或者它将返回-1以表示EOS。这意味着如果要正确读取 InputStream 中的字节,则必须使用循环。

There is no guarantee that read(byte[]) will fill the array you have provided, only that it will either read at least 1 byte (provided your array's length is > 0), or it will return -1 to signal the EOS. This means that if you want to read bytes from an InputStream correctly, you must use a loop.

循环你目前有一个错误。在循环的第一次迭代中,您将在缓冲区中读取一定数量的字节,但在第二次迭代中,您将覆盖这些字节中的一些或全部。看看 InputStream.read(byte [],int,int)

The loop you currently have has one bug in it. On the first iteration of the loop, you will read a certain number of bytes into your buffer, but on the second iteration you will overwrite some, or all, of those bytes. Take a look at InputStream.read(byte[], int, int).

这篇关于Java InputStream的read(byte [])方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆