【问题标题】:InputStream returns -1 before end of fileInputStream 在文件结束前返回 -1
【发布时间】:2023-03-22 01:26:01
【问题描述】:

我正在从服务器流式传输文件,然后将其流式传输回套接字(基本上是流代理)。这被用来缓冲一首歌曲。因此,一旦缓冲区已满,就不会再从套接字读取数据,直到缓冲区清空。但是,一旦读取了更多数据,InputStream 将再读取 X 个字节,然后突然返回一个 -1 表示文件结束,而实际上不是。是否发生超时?

下面是一些示例代码:

  InputStream data = realResponse.getEntity().getContent();

  ...some code...

  int totalBytes = 0;
  int count = 0;
  // Start streaming content.
  byte[] buff = new byte[1024 * 50];
  while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) {
    totalBytes += readBytes;

    Log(count + ": buffer:" + buff + " readBytes:" + readBytes + " total:" + totalBytes);
    client.getOutputStream().write(buff, 0, readBytes);
    Log("Finished write");
    count++;          

  }

日志示例如下所示:

0: buffer:B@45030a50 readBytes: 16164 total: 16164
1: buffer:B@45030a50 readBytes: 16384 total: 32548
...
100: buffer:B@45030a50 readBytes: 16384 total: 1654564
<a long pause here>
100: buffer:B@45030a50 readBytes: 16384 total: 1670948
100: buffer:B@45030a50 readBytes: 16384 total: 1687332
-1 Received

感谢任何帮助或建议

【问题讨论】:

  • 上面的日志好像和代码不匹配。日志中没有“完成写入”消息,也没有记录“-1 Received”的代码。 readBytes是否定义在totalBytes的范围内? count 设置在哪里? countreadBytes之间有关系吗?
  • 为了便于阅读,我稍微清理了日志并取出了“完成写入”,但忘记将其从代码中取出。 “-1 Received”位于未显示的日志语句中。 readBytes、totalBytes 和 count 都在范围内。 count 变量仅用于调试已完成的读/写次数。
  • 那个“isRunning”布尔检查怎么样?这是一个多线程应用程序吗?可能有什么东西将该标志设置为假吗?
  • 不,我在循环后检查了 readBytes,它确实是 -1。 totalBytes 也小于标头中的内容长度。此功能在其自己的线程中运行,因此不会将 isRunning 设置为 false。谢谢。
  • 每次都停在同一个地方吗?如果是这样,请在 UltraEdit32 之类的文件中打开文件并查看十六进制值。您应该能够查看该标记周围是否有会导致 EOF 通知的东西。它可能不是您的代码,而是文件本身。您是否尝试过其他文件?结果一样?

标签: java


【解决方案1】:

read() 在流的末尾而不是之前返回 -1。如果你比预期提前-1,数据比预期短,或者服务器比预期提前结束。

【讨论】:

  • 我假设服务器在几分钟内没有读取数据后正在关闭连接。重新打开连接并继续阅读的正确方法是什么?设置 Range 标头会是一个可接受的解决方案吗?或者是否有可能保持连接打开更长时间?谢谢。
  • @Nick:如果您使用的是 HTTP,则 Range 标头可能会起作用,具体取决于您的服务器。真正的问题是为什么要暂停?你在写什么?缓冲了吗?是插座吗?如果是这样,它是否有一个大的套接字发送缓冲区?另一端是什么?为什么 it 停滞不前?你真的一次得到 16384 字节吗?
  • 我一直在尝试使用 Range 标头,但是,我仍在处理它并且遇到了一些问题。发生暂停是因为接收端缓冲区已满,因此无法接受更多数据。我正在写入一个套接字,但在这种情况下,套接字发送缓冲区的大小是否重要,因为它是接收端的缓冲区正在填满?接收数据的另一端是移动设备上的 MediaPlayer 类,它试图使用少量内存,因此使用小缓冲区和停顿。是的,我实际上得到了 16483 个字节。
  • 我在使用java.util.ZipFile返回的InputStream对象时也遇到了这个问题。
  • 即使到达文件末尾,有人知道如何制作 IO 块吗?你知道,直到我请求的所有字节都被读取。
猜你喜欢
  • 2012-05-28
  • 1970-01-01
  • 2015-05-11
  • 2013-04-08
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
相关资源
最近更新 更多