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



首先介绍一下背景。它不需要回答实际的问题,但也许它会帮助你正确看待问题。

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

我已经在我本地硬盘上的12579个mp3文件上测试了这个库,它工作得很完美。没有一个IO错误。

当我在mp3文件位于web服务器上执行同样的事情时,我得到一个IO错误。其实不是错误。实际上,InputStream的read(byte[])方法的行为是不同的。

下面的例子将说明这个问题,当我试图从mp3文件中读取图像文件(.jpg, .gif, .png等)时发生。

// 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");

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

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

是正确的,InputStream.read(byte[])的一般行为,我需要把调用放在一个循环中,并保持读取字节,直到所需的字节数已被读取,或EOF已达到?类似下面的代码:

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[])的文档:

从输入流中读取一定数量的字节并将其存储到b.实际读取的字节数返回为一个整数。此方法阻塞,直到输入数据可用,结束文件被检测到,或者抛出异常。

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

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

因此我的问题是:一般来说,我能不能假设InputStream的read(byte[])方法会阻塞,直到整个字节数被读取(或达到EOF)?

。这就是为什么文档中说"实际读取的字节数"one_answers"尝试读取至少一个字节"。

我需要将调用放入循环中并继续读取字节,直到所需的字节数被读取

不用重新发明轮子,你可以在Jakarta Commons IO得到一个已经测试过的轮子。

最新更新