为什么FileInputStream read()没有阻塞?

我有一个Writer程序,它将一行文本写入文件,然后等待用户在写入另一行之前返回,然后退出。 只有在那之后文件才关闭。 代码:

public class Writer { Writer() { } public static String[] strings = { "Hello World", "Goodbye World" }; public static void main(String[] args) throws java.io.IOException { java.io.FileOutputStream pw = new java.io.FileOutputStream("myfile.txt"); for(String s : strings) { pw.write(s.getBytes()); System.in.read(); } pw.close(); } } 

首先开始:

java作家

然后我还有一个读者程序,只要文件的写入尚未完成(即尚未调用pw.close()),应该(我预期)阻止。 代码:

 public class ReaderFIS extends Object { ReaderFIS() { } public static void main(String[] args) throws Exception { java.io.FileInputStream in = new java.io.FileInputStream("myfile.txt"); int ch = -1; while((ch = in.read()) >= 0) { System.out.println("ch = " + ch); } System.out.println("Last ch = " + ch); System.out.println("exiting"); } } 

从…开始:

java ReaderFIS

现在我希望read()在读取第一个“Hello World”文本后阻塞,基于Javadoc文档中的这个:

从此输入流中读取一个字节的数据。 如果尚未提供输入,此方法将阻止。 通过: http : //docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

但阅读“Hello World”后,ReaderFIS立即完成,显然看到了EOF! 所以它不会阻止! 它转储字符值,然后转-1,然后打印“退出”。

输出:ch = 72 ch = 101 ch = 108 ch = 108 ch = 111 ch = 32 ch = 87 ch = 111 ch = 114 ch = 108 ch = 100最后ch = -1退出

我尝试的其他变体是:通过getChannel()读取,通过getChannel()检查是否可以使用lock()编辑,使用available(),使用缓冲区尝试read(),尝试readLine(),继续编写字符每次写入之间暂停500毫秒的文件,而不是写入任何只保持文件在Writer中打开的文件。
这些变化都不会导致ReaderFIS程序阻塞,它总是会完成。

为什么读者程序没有阻止 ? 我错过了一些非常明显的东西吗? 似乎ReaderFIS程序找到了EOF(-1),但为什么呢? 该文件尚未被Writer程序关闭。

“搞笑”旁注:System.in.read()正在阻止! (并等待用户按Enter键)。

PS:在Windows XP和Suse Linux上试过这个。 在Windows上,我无法在编写器运行时删除该文件(这是我所期望的)。

问候,马可

你的读者程序只是读取文件中的内容,然后点击结束并返回-1。 如果它在运行时包含的全部是“Hello World”,那么就可以读取它了。 如果你在输入作家后再次运行它,你应该看到“Hello World Goodbye World”。

没有更多的字节可用并且到达流的末尾是两个不同的事情。 这就是System.in.read()块和FileInputStream.read()没有的原因。

FileInputStream总是有输入可用:要么有剩余的字节要读取,要么有EOF,但通常它在读取时不会阻塞。 您可以在以下情况下被阻止:

  • 从控制台/终端读取
  • 从网络上阅读
  • 从管道中读取
  • 从任何等待数据的流中读取。

文件流不必等待数据,因为它们始终具有可用数据:在您的情况下, read()将基本上随机获得以下之一:

  • 旧版本的文件
  • 新版本的文件
  • 文件的半更新版本。

你有点没有抓到什么阻挡。 阻止IO是阻止程序执行直到IO操作完成的IO。 close只是从文件中断开程序。 如果您希望一个应用程序阻止另一个应用程序,您应该使用某种同步。

您不能将文件用作管道。

但是,您可以使用管道作为管道。

您可能需要一些东西来延迟实际读取数据。 请查看以下源代码: http : //www.java2s.com/Open-Source/Java/Web-Server/Jigsaw/org/w3c/jigsaw/ssi/DelayedInputStream.java.htm 。