简体   繁体   English

Java InputStream 的 read(byte[]) 方法

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

First some background.首先介绍一下背景。 Its not needed to answer the actual question, but maybe it'll help put things in perspective.它不需要回答实际问题,但也许它会有助于正确看待事情。

I have written an mp3 library in java (h) which reads out the information stored in the ID3 tag in an .mp3 file.我在 java (h) 中编写了一个 mp3 库,它读取存储在 .mp3 文件中的 ID3 标签中的信息。 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.有关歌曲的信息,如歌曲名称、发行歌曲的 CD、曲目编号等,都存储在 .mp3 文件开头的这个 ID3 标签中。

I have tested the library on 12,579 mp3 files which are located on my local hard drive, and it works flawlessly.我已经在位于我本地硬盘驱动器上的 12,579 个 mp3 文件上测试了该库,并且它可以完美运行。 Not a single IO error.没有一个 IO 错误。

When I perform the same thing where the mp3 files are located on a web server, I get an IO error.当我在 mp3 文件位于 Web 服务器上的位置执行相同的操作时,出现 IO 错误。 Well, not actually an error.嗯,实际上不是错误。 Actually its a difference in the behavior of the InputStream's read(byte[]) method.实际上它在 InputStream 的 read(byte[]) 方法的行为上有所不同。

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.下面的示例将说明当我尝试从 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");

So, my observation is: Calling inputStream.read(buffer);所以,我的观察是:调用 inputStream.read(buffer); always reads the entire number of bytes when the input stream is a FileInputStream.当输入流是 FileInputStream 时,总是读取整个字节数。 But it only reads a partial amount when I am using an input stream obtained from an http connection.但是当我使用从 http 连接获得的输入流时,它只读取部分数量。

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)?因此我的问题是:一般来说,我能不能假设 InputStream 的 read(byte[]) 方法会阻塞,直到读取了全部字节数(或达到 EOF)? That is, have I assumed behavior that is not true of the read(byte[]) method, and I've just gotten lucky working with FileInputStream?也就是说,我是否假设了 read(byte[]) 方法不正确的行为,并且我刚刚很幸运地使用了 FileInputStream?

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? InputStream.read(byte[]) 的正确和一般行为是否需要将调用置于循环中并继续读取字节直到读取到所需的字节数或达到 EOF? 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
}

Your conclusions are sound, take a look at the documentation for InputStream.read(byte[]) :你的结论是合理的,看看InputStream.read(byte[])的文档:

Reads some number of bytes from the input stream and stores them into the buffer array b.从输入流中读取一定数量的字节并将它们存储到缓冲区数组 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.此方法会阻塞,直到输入数据可用、检测到文件结尾或抛出异常。

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.不能保证read(byte[])会填充您提供的数组,只会读取至少 1 个字节(假设您的数组长度 > 0),或者它会返回 -1 以向 EOS 发出信号。 This means that if you want to read bytes from an InputStream correctly, you must use a loop.这意味着如果您想从InputStream正确读取字节,则必须使用循环。

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) .看看InputStream.read(byte[], int, int)

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)?因此我的问题是:一般来说,我能不能假设 InputStream 的 read(byte[]) 方法会阻塞,直到读取了全部字节数(或达到 EOF)?

No. That's why the documentation says "The number of bytes actually read" and "there is an attempt to read at least one byte."不。这就是文档说“实际读取的字节数”和“尝试读取至少一个字节”的原因。

I need to put the call in a loop and keep reading bytes until the desired number of bytes have been read我需要将调用置于循环中并继续读取字节,直到读取了所需的字节数

Rather than reinvent the wheel, you can get an already-tested wheel at Jakarta Commons IO .您可以在Jakarta Commons IO获得一个已经过测试的轮子,而不是重新发明轮子。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java InputStream的读取方法没有读取前几个字节的问题 - Problem with Java InputStream's read method not reading the first few bytes Java.io.InputStream.read()方法将每个数据类型读取为字节吗? - does Java.io.InputStream.read() Method read every datatype as byte? java.io.InputStream `read()` 方法与 `read(byte[] b)` 相比为什么输出不同的值? - Why java.io.InputStream `read()` method outputs different value if compared with `read(byte[] b)`? 如何通过java中InputStream中的read函数读取一个字节并将其作为int返回? - How is one byte read and returned as an int by read function in InputStream in java? Java InputStream.read(byte [],int,int)方法,如何阻塞,直到读取了确切的字节数 - Java InputStream.read(byte[], int, int) method, how to block until the exact number of bytes has been read java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int java.io.InputStream.read(byte[])” - java.lang.NullPointerException: Attempt to invoke virtual method 'int java.io.InputStream.read(byte[])' on a null object reference InputStream的read()方法如何实现? - How InputStream's read() method is implemented? InputStream.read(byte)方法如何工作? - How could InputStream.read(byte) method ever work? 理解Java InputStream读取方法的问题 - Problems understanding Java InputStream read method InputStream read()方法永远不会返回-1(Java) - InputStream read() method never returns -1 (Java)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM