为什么 FileInputStream read() 不阻塞?

发布于 2024-09-18 14:18:46 字数 2291 浏览 9 评论 0原文

我有一个 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

现在,根据 Javadoc 文档中的内容,我预计 read() 在读取第一个“Hello World”文本后会阻塞:

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

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

输出: 通道 = 72 通道 = 101 通道 = 108 通道 = 108 通道 = 111 通道 = 32 频道 = 87 通道 = 111 通道 = 114 通道 = 108 通道 = 100 最后一个频道 = -1 我尝试过的

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

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

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

PS:在 Windows XP 和 Suse Linux 上尝试过。在 Windows 上,当编写器运行时我无法删除该文件(正如我所期望的那样)。

问候, 马可

I've got a Writer program that writes one line of text to a file, then waits until the user hits return before it writes another line and then exits. Only after that is the file closed. The code:

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();
    }
}

Start first with:

java Writer

Then I also have a reader program that should (well I expected) block as long as the writing of the file hasn't finished yet (i.e pw.close() has not been called yet). The code:

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");
    }
}

Start with:

java ReaderFIS

Now I expected the read() to block after reading the first "Hello World" text, based on this in the Javadoc documentation:

Reads a byte of data from this input stream. This method blocks if no input is yet available.
Via: http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

But the ReaderFIS is immediately done after reading "Hello World" and apparently sees an EOF! So it does not block! It dumps the character values, then a -1 and then prints "exiting".

Output:
ch = 72
ch = 101
ch = 108
ch = 108
ch = 111
ch = 32
ch = 87
ch = 111
ch = 114
ch = 108
ch = 100
Last ch = -1
exiting

Other variations I tried were: reading via a getChannel(), checking via getChannel() if it can be lock()ed, using available(), trying read() using a buffer, trying readLine(), continously writing a character in the file with a 500msec pause in between each write, not writing anything just keeping the file open in the Writer.
None of these variations cause the ReaderFIS program to block, it always finishes.

Why does the reader program not block? Did I miss something soooo very obvious? It seems the ReaderFIS program finds an EOF (-1) but why? The file has not been closed yet by the Writer program.

"Funny" sidenote: the System.in.read() is blocking! (and waiting for the user to hit Enter).

PS: tried this on Windows XP and Suse Linux. On Windows I can't delete the file while the writer is running (which is as I expected).

Regards,
Marco

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

荆棘i 2024-09-25 14:18:46

FileInputStream 总是有可用的输入:要么还有字节需要读取,要么有 EOF,但一般情况下读取时不会阻塞。当您执行以下操作时,您可能会被阻止:

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

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

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

FileInputStream always has input available: either there are bytes left to read or there is an EOF, but in general it will not block when reading. You can get blocked when you are:

  • reading from a console / terminal
  • reading from the network
  • reading from a pipe
  • reading from whatever stream that is waiting for data.

File Streams do not have to wait for data as they always have data available: in your case read() will get, basically at random, one of:

  • the old version of the file
  • the new version of the file
  • half-updated version of the file.
吐个泡泡 2024-09-25 14:18:46

您的阅读器程序将读取文件中的所有内容,然后到达末尾并返回 -1。如果您运行时它包含的全部内容是“Hello World”,那么这就是它能够读取的全部内容。如果在编写器中按回车键后再次运行它,您应该看到“Hello World Goodbye World”。

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

Your reader program is just going to read whatever is in the file, then hit the end and return -1. If all it contains at the time you run it is "Hello World", then that's all it will be able to read. If you run it again after you've hit enter in your writer, you should see "Hello World Goodbye World".

Having no more bytes available and hitting the end of a stream are two different things. That's why System.in.read() blocks and FileInputStream.read() doesn't.

审判长 2024-09-25 14:18:46

您不能将文件用作管道。

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

You can't use files as pipes.

However you can use pipes as pipes.

笑叹一世浮沉 2024-09-25 14:18:46

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

you slightly didn't catch what is blocking. Blocking IO is ones that block execution of program until IO operation finish. close just disconnect program from file. If you want one app to block another you should use some sort of synchronization.

¢蛋碎的人ぎ生 2024-09-25 14:18:46

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

You may need something to delay the actual reading of data. Check this source code : http://www.java2s.com/Open-Source/Java/Web-Server/Jigsaw/org/w3c/jigsaw/ssi/DelayedInputStream.java.htm.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文