java - InputStream的read()方法是如何实现的?

标签 java sockets inputstream

对于特定任务,我尝试重写扩展 InputStream 的自定义类的 read() 方法。

到目前为止我的实现是:

private ArrayList<byte[]> inputBuffer = new ArrayList<>(); 
...
@Override
public int read(@NonNull byte[] b) throws IOException {
    if (inputBuffer.size() > 0) {
        b = inputBuffer.get(0);
        inputBuffer.remove(0);
    } else
        return -1;

    return b.length;
}

我正在将数据添加到我的 InputStream 中,如下所示:

boolean writeDataToInputStream(byte[] data) {
    int arrSize = inputBuffer.size();
    if (data.length > 0) {
        inputBuffer.add(data);
    }
    return arrSize < inputBuffer.size();
}

我已阅读文档,我知道此方法默认情况下如何工作。但我需要以某种方式将 ArrayList 元素传递给输入参数 byte[] b

我已经用java编写了几年代码,但我从未关注过这个方法是如何实际实现的。如何将数据传递给传入参数并返回 ArrayList 元素写入的字节数?

由于我的架构,我必须使用专门用于带输入和输出流的 BLE 的自定义套接字,其中我使用 WiFi 套接字、BT 套接字。

请为我揭开这个谜团。

最佳答案

当您创建自己的InputStream时,由于它是一个抽象方法,所以您必须实现的唯一方法是 read()这也比实现 read(byte[] b) 和/或 read(byte b[], int off, int len) 更不容易出错。此外,请注意 read(byte b[], int off, int len) 的默认实现已经为您检查了参数,因此除非您想自己重新验证参数,否则您应该实现 仅 read()

所以在你的情况下这个方法可能是:

// Current index in the last byte array read
private int index;
private List<byte[]> inputBuffer = new ArrayList<>();
...
@Override
public int read() throws IOException {
   if (inputBuffer.isEmpty()) {
        return -1;
    }
    // Get first element of the List
    byte[] bytes = inputBuffer.get(0);
    // Get the byte corresponding to the index and post increment the current index
    byte result = bytes[index++];
    if (index >= bytes.length) {
        // It was the last index of the byte array so we remove it from the list
        // and reset the current index
        inputBuffer.remove(0);
        index = 0;
    }
    return result;
}

但是,如果您确实想实现read(byte b[], int off, int len),则它的样子如下:

@Override
public int read(byte b[], int off, int len) throws IOException {
    // Check parameters
    if (b == null) {
        throw new NullPointerException();
    } else if (off < 0 || len < 0 || len > b.length - off) {
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {
        return 0;
    }
    if (inputBuffer.isEmpty()) {
        return -1;
    }
    int read = 0;
    // Iterate as long as don't get the expected bytes amount and the list is not empty
    do {
        byte[] bytes = inputBuffer.get(0);
        int lg = Math.min(bytes.length - index, len);
        // Copy the bytes from "bytes" to "b"
        System.arraycopy(bytes, index, b, off, lg);
        // Update all counters
        read += lg;
        off += lg;
        index += lg;
        len -= lg;
        if (index >= bytes.length) {
            // It was the last index of the byte array so we remove it from the list
            // and reset the current index
            inputBuffer.remove(0);
            index = 0;
        }
    } while (read < len && !inputBuffer.isEmpty());

    return read;
}

关于java - InputStream的read()方法是如何实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40916355/

相关文章:

java - 以对象为键的映射

Java/Groovy Socket - 以非阻塞方式检测正在关闭的套接字

java - 通过 ImageMagick 流式传输的 JPEG 文件与原始文件的大小不同

java - Java 语法解析器的正则表达式

java - 从 BufferedImage 获取像素数据

java - 将组件添加到 JFrame 内的 JPanel

c - 唯一标识套接字

java - SSL 套接字 : no cipher suites in common error

android - 你如何在 MediaPlayer 上播放 Android InputStream?

c++ - 从标准输入中捕获字符,而无需等待按下回车键