为什么 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
现在,根据 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
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:
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:您的阅读器程序将读取文件中的所有内容,然后到达末尾并返回 -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.
您不能将文件用作管道。
但是,您可以使用管道作为管道。
You can't use files as pipes.
However you can use pipes as pipes.
你稍微没明白是什么阻碍了。阻塞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.您可能需要一些东西来延迟数据的实际读取。检查此源代码: 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.