perl 打印到文件和 STDOUT 这是文件

Das*_*ham 0 perl file-handling

我的程序试图打印到一个文件,它是标准输出。比如说,打印“这里的文字”;打印到文件 x.log ,而我也尝试使用文件处理程序方法打印到文件 x.log ,如print FH1 "text here"; . 我注意到当首先提供文件处理程序方法语句,然后是 STDOUT 过程时。我的第二个打印可以覆盖第一个。我想知道更多关于为什么会发生这种情况的信息。

这让我想到了竞争条件,或者文件处理程序比 STDOUT 打印语句相对慢(如果它通过缓冲区?)。我不确定这是否是 Perl 的工作方式。Perl 版本 - 5.22.0

Ste*_*ich 5

据我了解,你的程序基本上是这样的:

open(my $fh,'>','foobar.txt');
print $fh "foo\n";
print "bar\n"; # prints to STDOUT
Run Code Online (Sandbox Code Playgroud)

然后你以一种方式使用它,STDOUT 在 shell 中被重定向到你的程序中已经打开的同一个文件:

$ perl test.pl > foobar.txt
Run Code Online (Sandbox Code Playgroud)

这将打开同一文件的两个独立文件句柄:一个在您的程序中,另一个在您启动程序的 shell 中。两个文件句柄管理自己的写入文件位置,从位置 0 开始并在每次写入后推进位置。

由于这些文件句柄彼此独立,因此它们不会关心当前是否有其他文件句柄在处理此文件,无论这些其他文件句柄是在程序内部还是外部。这意味着这些写入将相互覆盖。

除此之外,还有内部缓冲完成,即每个print将首先导致写入某个内部缓冲区,并且可能立即导致写入文件句柄。数据何时写入文件句柄取决于文件句柄的模式,即无缓冲、行缓冲或特定大小的缓冲区。这使得结果有点不可预测。

如果您不想要这种行为,但仍想使用多个文件句柄写入同一个文件,您最好使用附加模式,即打开 with>>而不是>在 Perl 代码和 shell 中打开。这将确保所有数据都将附加到文件末尾,而不是写入文件句柄维护的文件位置。这样数据就不会被覆盖。此外,您可能希望使文件句柄无缓冲,以便文件中的数据以与print完成的语句相同的顺序结束:

open(my $fh,'>>','foobar.txt');
$fh->autoflush(1); # make $fh unbuffered
$|=1;   # make STDOUT unbuffered
print $fh "foo\n";
print "bar\n"; # prints to STDOUT

$ perl test.pl >> foobar.txt
Run Code Online (Sandbox Code Playgroud)

  • @Grinnz:追加模式是通过`O_APPEND` 标志打开的。来自[手册页](http://man7.org/linux/man-pages/man2/open.2.html)关于这个标志:*“在每次写入(2)之前,文件偏移量位于末尾文件,就像使用 lseek(2) 一样。文件偏移量的修改和写操作作为单个原子步骤执行。"*. (2认同)