文件句柄在 Perl 中无法正常工作
File handles not working properly in Perl
我尝试将两个文件句柄初始化为 NULL,然后在我的程序中使用它。
这是我的代码:
my $fh1 = " ";
my $fh2 = " ";
open($fh1, ">", $fname1);
open($fh2, ">", $fname2);
print $fh1 "HI this is fh1";
执行后,我的文件包含:
fname1 为空
fname2 包含
Hi this is fh1
哪里出错了?
为什么 fname1 是空的,而 fname2 包含一个字符串,即使我没有在 fh2 中插入任何字符串?
您已将 $fh1
和 $fh2
设置为相同的值(一个 space 字符,而不是 NULL),因此它们为 I/O 引用相同的底层类型团.
Perl 中的文件句柄是一种特殊的变量类型,称为 glob 或 typeglob。在过去的 Perl 4 时代,您总是将 glob 称为字符串,通常称为裸词。裸词 STDIN
、STDOUT
和 STDERR
是这个简单时代的遗物。
如今,您可以(通常应该)使用词法文件句柄,但对类型团的底层引用仍然存在。比如你可以写
my $fh = 'STDOUT';
print $fh "hello world\n";
这将做与
完全相同的事情
print STDOUT "hello world\n";
现在,如果您将未初始化的标量作为第一个参数传递给 open
,Perl 将为它分配一个任意类型团。您可能不需要知道它是哪个 typeglob。
但是如果 open
的参数已经初始化,Perl 将使用带有该参数值的类型团。因此,这段代码将创建数据并将其添加到文件中:
my $fh = "FOO";
open $fh, '>', '/tmp/1';
print FOO "This is going into /tmp/1\n";
close $fh;
现在我们可以看看你的例子。您已将 $fh1
和 $fh2
设置为相同的值——一个由 space 字符组成的字符串。因此,您对 $fh1
的 open
调用会在名为 " "
的类型团与输出流的文件描述符之间建立关联 $fname1
.
当您在 $fh2
上调用 open
时,您正在重复使用名为 " "
的类型团,这将自动关闭使用相同类型团 ($fh1
) 的其他文件句柄,就像你说 open FOO, ">/tmp/1"; open FOO, ">/tmp/2"
一样,第二个 open
调用将隐式 close
第一个文件句柄。
现在您在 $fh1
上打印,它引用名为 " "
的类型团,它与文件 $fname2
的输出流关联,这就是输出的位置。
初始化 $fh1
和 $fh2
是一个错误。只保留它们未定义:
my ($fh1, $fh2);
open $fh1, ">", ... # assigns $fh1 to arbitrary typeglob
open $fh2, ">", ... # assigns $fh2 to different arbitrary typeglob
你根本不应该初始化你的文件句柄,否则 Perl 会尝试使用那个值作为文件句柄而不是创建一个新的。在这种情况下,您在文件句柄 ' '
(单个 space)上打开了 $fname1
,然后在同一文件句柄上打开了 $fname2
,这关闭了 $fname1
.
与其单独声明文件句柄,不如在open
语句中声明它们,像这样
open my $fh1, '>', $fname1;
open my $fh2, '>', $fname2;
这样就不会出错了
我尝试将两个文件句柄初始化为 NULL,然后在我的程序中使用它。
这是我的代码:
my $fh1 = " ";
my $fh2 = " ";
open($fh1, ">", $fname1);
open($fh2, ">", $fname2);
print $fh1 "HI this is fh1";
执行后,我的文件包含:
fname1 为空
fname2 包含
Hi this is fh1
哪里出错了?
为什么 fname1 是空的,而 fname2 包含一个字符串,即使我没有在 fh2 中插入任何字符串?
您已将 $fh1
和 $fh2
设置为相同的值(一个 space 字符,而不是 NULL),因此它们为 I/O 引用相同的底层类型团.
Perl 中的文件句柄是一种特殊的变量类型,称为 glob 或 typeglob。在过去的 Perl 4 时代,您总是将 glob 称为字符串,通常称为裸词。裸词 STDIN
、STDOUT
和 STDERR
是这个简单时代的遗物。
如今,您可以(通常应该)使用词法文件句柄,但对类型团的底层引用仍然存在。比如你可以写
my $fh = 'STDOUT';
print $fh "hello world\n";
这将做与
完全相同的事情print STDOUT "hello world\n";
现在,如果您将未初始化的标量作为第一个参数传递给 open
,Perl 将为它分配一个任意类型团。您可能不需要知道它是哪个 typeglob。
但是如果 open
的参数已经初始化,Perl 将使用带有该参数值的类型团。因此,这段代码将创建数据并将其添加到文件中:
my $fh = "FOO";
open $fh, '>', '/tmp/1';
print FOO "This is going into /tmp/1\n";
close $fh;
现在我们可以看看你的例子。您已将 $fh1
和 $fh2
设置为相同的值——一个由 space 字符组成的字符串。因此,您对 $fh1
的 open
调用会在名为 " "
的类型团与输出流的文件描述符之间建立关联 $fname1
.
当您在 $fh2
上调用 open
时,您正在重复使用名为 " "
的类型团,这将自动关闭使用相同类型团 ($fh1
) 的其他文件句柄,就像你说 open FOO, ">/tmp/1"; open FOO, ">/tmp/2"
一样,第二个 open
调用将隐式 close
第一个文件句柄。
现在您在 $fh1
上打印,它引用名为 " "
的类型团,它与文件 $fname2
的输出流关联,这就是输出的位置。
初始化 $fh1
和 $fh2
是一个错误。只保留它们未定义:
my ($fh1, $fh2);
open $fh1, ">", ... # assigns $fh1 to arbitrary typeglob
open $fh2, ">", ... # assigns $fh2 to different arbitrary typeglob
你根本不应该初始化你的文件句柄,否则 Perl 会尝试使用那个值作为文件句柄而不是创建一个新的。在这种情况下,您在文件句柄 ' '
(单个 space)上打开了 $fname1
,然后在同一文件句柄上打开了 $fname2
,这关闭了 $fname1
.
与其单独声明文件句柄,不如在open
语句中声明它们,像这样
open my $fh1, '>', $fname1;
open my $fh2, '>', $fname2;
这样就不会出错了