InputStream.available()在Java中做什么?

时间:2010-09-12 15:27:45

标签: java blocking inputstream

Java InputStream.available()做了什么?我阅读了文档,但我仍然无法解决。

医生说:

  

返回此输入流可以读取(或跳过)的字节数,而不会被此输入流的方法的下一个调用者阻塞。下一个调用者可能是同一个线程或另一个线程。

     

类InputStream的可用方法始终返回0.

阻止是什么意思?它只是意味着同步通话吗?

最重要的是,available()方法的目的是什么?

4 个答案:

答案 0 :(得分:40)

在InputStreams中,read()调用被称为“阻塞”方法调用。这意味着如果在方法调用时没有可用的数据,该方法将等待数据可用。

available()方法告诉您在read()调用阻止程序执行流程之前可以读取多少字节。在大多数输入流中,对read()的所有调用都是阻塞的,这就是默认情况下可用返回0的原因。

但是,在某些流(例如BufferedInputStream,具有内部缓冲区)上,一些字节被读取并保存在内存中,因此您可以在不阻塞程序流的情况下读取它们。在这种情况下,available()方法会告诉您缓冲区中保留了多少字节。

答案 1 :(得分:26)

阻止与此处的线程或同步无关。相反,它与阻止IO有关(有关详细信息,请参阅this)。如果您发出读取请求,并且该通道没有可用,则阻塞调用将等待(或阻止),直到数据可用(或通道关闭,抛出异常等)。

那么为什么要使用available()?因此,您可以确定要读取的字节数,或确定是否要阻止。

请注意,Java也具有非阻塞IO功能。有关详细信息,请参阅here

答案 2 :(得分:-1)

available()的一个可能实用的用法正在使用它来选择合理的缓冲区长度。

static final int LEN = 4096;

long copy(InputStream in, OutputStream out) throws IOException {
    int count = 0L;
    int avl = in.available();
    if (avl == 0) {
        // 0 returned without IOException? possibly mean eof?
        return 0L;
    }
    //byte[] buf = new byte[avl == 0 ? LEN : Math.min(avl, LEN)];
    byte[] buf = new byte[Math.min(avl, LEN)];
    for (int len; (len = in.read(buf)) != -1; count+= len) {
        out.write(buf, 0, len);
    }
    return count;
}

该文件说,

  

返回:估计可以从此输入流中无阻塞地读取(或跳过)的字节数,或者当 0到达结束时输入流

  

如果通过调用IOException方法关闭此输入流,则此方法的子类'实现可以选择抛出close()

<强>更新

我已经知道不推荐这个想法了。我甚至在JDK文档警告之前就知道这种风险。 (我曾尝试从几个GB大小available的{​​{1}}中分配一个缓冲区。)

JDK8/InputStream#available

  

使用此方法的返回值来分配用于保存此流中所有数据的缓冲区是绝对正确的。

JDK5/InputStream#availabe

但是,在编程中,不应该有FileInputStreamnever代码。 这就是我所相信的。

答案 3 :(得分:-2)

考虑一下你是否编写了非常糟糕的软件..然后你编写了一个操作系统。

此操作系统在其他方面输入键盘输入。

所以你要求你的操作系统去获取一些键盘输入,但没有按下任何键,缓冲区也没有。 然后你的整个操作系统将被挂起,直到它获得键盘输入。

将此与“向前看”对比,您在调用之前询问KB是否有任何字符。 你得到的答案是否定的,所以你的操作系统会去做其他事情。

这就是为什么你应该关心,现在如果你将其与其他所有可能阻塞的任务相乘,你就会明白为什么“向前看”是至关重要的。

因为它也适用于OUTPUT:磁盘驱动器接口的内存也可以比处理磁盘驱动器更快地将数据泄漏到磁盘驱动器。 如果您不知道驱动器缓冲区充满了数据,那么任务将阻塞,直到缓冲区可以接受更多数据。

这也突出了“很少有用的用途”的废话。