【问题标题】:Read all InputStream values at once into a byte[] array一次将所有 InputStream 值读入 byte[] 数组
【发布时间】:2015-08-23 09:35:10
【问题描述】:

有没有一种无需使用Apache IO lib 即可一次读取所有 InputStream 值的方法?

我正在读取 IR 信号并将其从 InputStream 保存到 byte[] 数组中。在调试时,我注意到它只有在我在那里放置延迟时才有效,以便我一次读取所有字节然后处理它。

有更聪明的方法吗?

代码:

 public void run() {
        Log.i(TAG, "BEGIN mConnectedThread");
        byte[] buffer = new byte[100];
        int numberOfBytes;
        removeSharedPrefs("mSharedPrefs");
        // Keep listening to the InputStream while connected
        while (true) {
            try {
                // Read from the InputStream
                numberOfBytes = mmInStream.read(buffer);
                Thread.sleep(700);  //If I stop it here for a while, all works fine, because array is fully populated
                if (numberOfBytes  > 90){
                    // GET AXIS VALUES FROM THE SHARED PREFS
                    String[] refValues = loadArray("gestureBuffer", context);
                    if (refValues!=null && refValues.length>90) {
                        int incorrectPoints;
                        if ((incorrectPoints = checkIfGesureIsSameAsPrevious(buffer, refValues, numberOfBytes)) < 5) {
                           //Correct
                        } else {
                           //Incorrect
                        }
                    }
                    saveArray(buffer, numberOfBytes);
                }else{
                    System.out.println("Transmission of the data was corrupted.");
                }
                buffer = new byte[100];
                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(Constants.MESSAGE_READ, numberOfBytes, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "disconnected", e);
                connectionLost();
                // Start the service over to restart listening mode
                BluetoothChatService.this.start();
                break;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

【问题讨论】:

  • 永远不要假设当你要求读取 N 个字节时,你会得到 N 个字节。你可以得到 0 到 N 个字节,但你永远不能确定你会得到 N 个字节。始终使用循环读取。添加 sleep() 不是解决方案。它可能碰巧起作用,因为它足以让字节可用,但这取决于网络、机器等。在 Java 7 及更高版本中,有一些快捷方法可以完全读取流,但在 Java 6 中没有,AFAIK .也许android有这样的实用程序,但我对Android的了解不够了解。反正自己写很简单。
  • @JBNizet,谢谢。我会尝试做循环的事情,如果你希望你可以回答这个问题。也许给我一些示例代码。非常感谢。能否请您检查一下 Sebastians 的答案是否正确?
  • 我认为它是正确的,是的。我对nio不是很了解,你为什么不测试一下?
  • 我要测试一下,我只是赶时间。很抱歉。
  • 定义“所有 InputStream 值”。大多数情况下,您只需要继续阅读即可。在网络代码中休眠并不能真正解决任何问题。无需从流更改为 NIO。

标签: java android inputstream


【解决方案1】:

编辑:

我的旧答案是错误的,请参阅 EJP 评论!请不要使用它。 ByteChannel 的行为取决于 InputStream 是否阻塞。

这就是我建议的原因,您只需从 Apache Commons 复制 IOUtils.read

public static int read(final InputStream input, final byte[] buffer) throws IOException {
    int remaining = buffer.length;
    while (remaining > 0) {
        final int location = buffer.length - remaining;
        final int count = input.read(buffer, location, remaining);
        if (count == -1) { // EOF
            break;
        }
        remaining -= count;
    }
    return buffer.length - remaining;
}

旧答案:

您可以使用 ByteChannels 并读入一个 ByteBuffer:

ReadableByteChannel c = Channels.newChannel(inputstream);
ByteBuffer buf = ByteBuffer.allocate(numBytesExpected);
int numBytesActuallyRead = c.read(buf);

此读取方法尝试读取与缓冲区中剩余空间一样多的字节。如果流在缓冲区完全填满之前结束,则返回实际读取的字节数。见JavaDoc

【讨论】:

  • 没有真正的帮助,每次读取分配一个新的ByteBuffer 是浪费的。没有它,您可以编写等效的流代码。 InputStream.read() 也返回一个计数。
  • 我一回到家就去试试。非常感谢 Sebastian 和 @EJP。
猜你喜欢
  • 2019-05-17
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
  • 2011-08-10
  • 2012-02-07
  • 1970-01-01
相关资源
最近更新 更多