6

我有一个 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();
    }
}

首先开始:

写手

然后我还有一个阅读器程序,只要文件的写入尚未完成(即 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阅读器FIS

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

从此输入流中读取一个字节的数据。如果还没有输入可用,则此方法会阻塞。通过:http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

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

输出: 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() 检查是否可以锁定(),使用 available(),尝试使用缓冲区读取 read(),尝试 readLine(),连续写入一个字符文件在每次写入之间有 500 毫秒的暂停,不写任何东西,只是在 Writer 中保持文件打开。
这些变化都不会导致 ReaderFIS 程序阻塞,它总是会结束。

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

“有趣”的旁注: System.in.read() 被阻塞了!(并等待用户按 Enter)。

PS:在 Windows XP 和 Suse Linux 上试过这个。在 Windows 上,当编写器运行时,我无法删除文件(正如我所料)。

问候, 马可

4

5 回答 5

2

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

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

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

  • 文件的旧版本
  • 文件的新版本
  • 文件的半更新版本。
于 2010-09-09T21:16:43.973 回答
1

您的阅读器程序将读取文件中的任何内容,然后结束并返回 -1。如果它在您运行时只包含“Hello World”,那么它就可以读取所有内容。如果您在编写器中按 Enter 后再次运行它,您应该会看到“Hello World Goodbye World”。

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

于 2010-09-09T15:17:29.223 回答
1

您不能将文件用作管道。

但是,您可以将管道用作管道。

于 2010-09-09T23:55:39.437 回答
0

你稍微没有抓住什么是阻塞。阻塞 IO 是阻塞程序执行直到 IO 操作完成。close只需断开程序与文件的连接。如果您希望一个应用程序阻止另一个应用程序,您应该使用某种同步。

于 2010-09-09T15:12:15.600 回答
0

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

于 2012-05-22T14:53:00.847 回答