当前位置: 首页 > 知识库问答 >
问题:

输入流。available()和从oracle完全读取文件注释

蓝鸿哲
2023-03-14

根据:

请注意,虽然InputStream的一些实现将返回流中的总字节数,但许多实现不会返回。使用此方法的返回值来分配一个缓冲区以保存此流中的所有数据永远都是不正确的。

来自:

http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available()

还有这张便条

In particular, code of the form

int n = in.available();
byte buf = new byte[n];
in.read(buf); 

is not guaranteed to read all of the remaining bytes from the given input stream.

http://docs.oracle.com/javase/8/docs/technotes/guides/io/troubleshooting.html

这是否意味着使用下面的函数会导致无法完全读取文件?

/**
 * Reads a file from /raw/res/ and returns it as a byte array
 * @param res Resources instance for Mosembro
 * @param resourceId ID of resource (ex: R.raw.resource_name)
 * @return byte[] if successful, null otherwise
 */
public static byte[] readRawByteArray(Resources res, int resourceId)
{
    InputStream is = null;
    byte[] raw = new byte[] {};
    try {
        is = res.openRawResource(resourceId);
        raw = new byte[is.available()];
        is.read(raw);
    }
    catch (IOException e) {
        e.printStackTrace();
        raw = null;
    }
    finally {
        try {
            is.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    return raw;
}

共有2个答案

阎功
2023-03-14

是的,它不一定读全部。比如随机访问文件。读取(字节[])而不是随机访问文件。准备就绪(字节[])。此外,代码实际读取0字节。

如果它是像文件系统这样的慢速设备,它可能只读取第一个块。

原理:文件由底层系统软件读取,通常是缓冲的,因此内存中已经有几个块,有时甚至已经在进一步读取。软件读取异步块,如果试图读取的数据超过系统已经读取的数据,则读取块。

所以一般来说,软件中有一个块的读取循环,并定期读取读取操作块,直到物理读取足够缓冲。

要实现无阻塞,您需要执行以下操作:

InputStream is = res.openRawResource(resourceId);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (;;) {
    // Read bytes until no longer available:
    for (;;) {
        int n = is.available();
        if (n == 0) {
            break;
        }
        byte[] part = new byte[n];
        int nread = is.read(part);
        assert nread == n;
        baos.write(part, 0, nread);
    }
    // Still a probably blocking read:
    byte[] part = new byte[128];
    int nread = is.read(part);
    if (nread <= 0) {
        break; // End of file
    }
    baos.write(part, 0, nread);
}
return baos.toByteArray();

现在,在复制该代码之前,只需立即执行阻塞读取循环。除非您可以在读取其余数据时处理部分数据,否则我看不到使用可用()的优势。

尹庆
2023-03-14

available()返回可以在不阻塞的情况下读取的字节数。该数字(可以为零)与文件的总长度之间没有必要的相关性。

 类似资料:
  • 问题内容: 我正在使用从运行约一分钟的进程中读取stdout。 我该如何stdout以流方式打印出该流程的每一行,以便可以看到生成的输出,但仍然阻止该流程终止,然后再继续? 似乎一次给出所有输出。 问题答案: 这是一个简单的示例(不检查错误): 如果ls结束太快,则while循环可能会在你读取所有数据之前结束。 你可以通过以下方式在中捕获其余部分:

  • 我目前正试图从服务器读取图像文件,但得到的数据不完整或 这与缓冲区大小有关吗?我已经尝试使用静态大小而不是ContentLength。敬请指教。

  • 问题内容: 如果我有此代码,该如何保留原始文件的文件名或将其重新分配给新文件名?: 问题答案: 可以创建输入流以从文件或任何其他数据源读取。因此,将文件名附加到输入流没有任何意义。查看该类是否公开了该数据(您甚至可以使用反射来查看该类的内部)。请注意,创建者或犯了一个设计错误,没有公开此信息,或者您正在尝试制作此信息。

  • 问题内容: 我在文件中有以下JSON : 如何使用PHP 添加到文件中? 这是我到目前为止的内容: 这给了我一个致命错误:无法在此行上将stdClass类型的对象用作数组: 我正在使用PHP5.2。有什么想法吗?谢谢! 问题答案: 错误消息中的线索是-如果您查看文档以了解它可能需要第二个参数,该参数控制返回数组还是对象-它默认为object。 因此,将您的通话更改为 并且它将返回一个关联数组,您的

  • 问题内容: 这是一个有点奇怪的请求,但我正在寻找一种方法来将列表写入文件,然后再读回去。 我没有办法重新制作列表,以使它们如下面的示例所示正确地形成/格式化。 我的列表具有如下数据: 问题答案: 如果您不需要它是人类可读/可编辑的,则最简单的解决方案是使用。 来写: 读书: 如果您 确实 需要使它们易于阅读,则我们需要更多信息。 如果保证是没有嵌入换行符的字符串列表,则只需每行写一个: 如果它们是

  • 我试图从一个json文件中读取值,该文件直接放在我的资源文件夹中。我能够在bootrun中成功运行它,没有任何错误 然而,当用上面的代码创建一个JAR时,我得到的异常是fileNotFound java-jar app-0.0.1-SNAPSHOT-plain。罐子