为什么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 。