请注意 - 我不是在寻找打开/读取文件的“正确”方式,也不是每次都打开/读取文件的方式。我只是想知道大多数人使用什么方式,并且可能同时学习一些新方法:)*
我的Perl程序中一个非常常见的代码块是打开一个文件并读取或写入它。我已经看到了很多这样做的方法,多年来我执行这项任务的风格发生了变化。我只是想知道 best (如果有最好的方法)方法是做什么的呢?
我以前打开过这样的文件:
my $input_file = "/path/to/my/file";
open INPUT_FILE, "<$input_file" || die "Can't open $input_file: $!\n";
但我认为错误捕获存在问题。
添加括号似乎可以修复错误捕获:
open (INPUT_FILE, "<$input_file") || die "Can't open $input_file: $!\n";
我知道你也可以为一个变量分配一个文件句柄,所以不像我上面那样使用“INPUT_FILE”,我可以使用$ input_filehandle - 这样更好吗?
对于读取文件,如果它很小,那么globbing有什么问题吗?
my @array = <INPUT_FILE>;
或
my $file_contents = join( "\n", <INPUT_FILE> );
或者你应该总是循环,像这样:
my @array;
while (<INPUT_FILE>) {
push(@array, $_);
}
我知道有很多方法可以在perl中完成任务,我只是想知道在文件中是否有打开和读取的首选/标准方法?
答案 0 :(得分:58)
没有通用的标准,但有理由偏爱这一个或另一个。我的首选形式是:
open( my $input_fh, "<", $input_file ) || die "Can't open $input_file: $!";
原因是:
如果文件很小并且您知道您想要所有行,则以下内容非常好:
my @lines = <$input_fh>;
如果您需要将所有行作为单个字符串处理,您甚至可以这样做:
my $text = join('', <$input_fh>);
对于长文件,您需要使用while迭代行,或使用read。
答案 1 :(得分:15)
如果您希望将整个文件作为单个字符串,则无需迭代它。
use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
my $data = q{};
{
local $RS = undef; # This makes it just read the whole thing,
my $fh;
croak "Can't open $input_file: $!\n" if not open $fh, '<', $input_file;
$data = <$fh>;
croak 'Some Error During Close :/ ' if not close $fh;
}
以上内容满足perlcritic --brutal
,这是测试“最佳实践”:)的好方法。 $input_file
在这里仍未定义,但其余部分是犹太洁食。
答案 2 :(得分:13)
不得不在任何地方写'或死'让我疯狂。我打开文件的首选方式如下:
use autodie;
open(my $image_fh, '<', $filename);
虽然打字很少,但有很多重要的事情需要注意:
我们正在使用autodie pragma,这意味着如果出现问题,所有Perl的内置函数都会抛出异常。它消除了在代码中编写or die ...
的需要,它产生友好的,人类可读的错误消息,并具有词法范围。它可以从CPAN获得。
我们正在使用open的三参数版本。这意味着即使我们有一个包含<
,>
或|
等字符的有趣文件名,Perl仍会做正确的事情。在OSCON的 Perl Security 教程中,我展示了一些方法来让2个参数open
行为不端。本教程的注释适用于free download from Perl Training Australia。
我们正在使用标量文件句柄。这意味着我们不会巧合地关闭其他人的同名文件句柄,如果我们使用包文件句柄就会发生这种情况。这也意味着strict
可以发现拼写错误,并且如果超出范围,我们的文件句柄将自动清理。
我们正在使用有意义的文件句柄。在这种情况下,我们似乎要写一个图像。
文件句柄以_fh
结尾。如果我们看到我们像常规标量一样使用它,那么我们就知道这可能是一个错误。
答案 3 :(得分:11)
如果您的文件足够小,可以将整个内容读入内存,请使用File::Slurp。它使用非常简单的API读取和写入完整文件,并且它会执行所有错误检查,因此您不必这样做。
答案 4 :(得分:6)
没有最好的方法来打开和阅读文件。这是一个错误的问题。文件中有什么?您在任何时候需要多少数据?您是否一次需要所有数据?您需要对数据做什么?在考虑如何打开和阅读文件之前,您需要弄清楚这些。
您现在正在做的任何事情都会导致您出现问题吗?如果没有,你有没有更好的问题要解决? :)
你的大多数问题仅仅是语法,这些都在Perl文档中得到了解答(特别是(perlopentut)。你可能还想选择Learning Perl,这可以解决你遇到的大多数问题在你的问题中。
祝你好运,:))
答案 5 :(得分:5)
对于OO,我喜欢:
use FileHandle;
...
my $handle = FileHandle->new( "< $file_to_read" );
croak( "Could not open '$file_to_read'" ) unless $handle;
...
my $line1 = <$handle>;
my $line2 = $handle->getline;
my @lines = $handle->getlines;
$handle->close;
答案 6 :(得分:5)
确实,在Perl中打开文件的方法与
一样多$files_in_the_known_universe * $perl_programmers
...但看到谁通常以哪种方式做到这一点仍然很有趣。我首选的啜饮形式(一次读取整个文件)是:
use strict;
use warnings;
use IO::File;
my $file = shift @ARGV or die "what file?";
my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
my $data = do { local $/; <$fh> };
$fh->close();
# If you didn't just run out of memory, you have:
printf "%d characters (possibly bytes)\n", length($data);
当逐行时:
my $fh = IO::File->new( $file, '<' ) or die "$file: $!";
while ( my $line = <$fh> ) {
print "Better than cat: $line";
}
$fh->close();
警告当然是这些:这些只是我致力于日常工作的肌肉记忆的方法,它们可能完全不适合你想要解决的问题。
答案 7 :(得分:4)
我曾经使用过
open (FILEIN, "<", $inputfile) or die "...";
my @FileContents = <FILEIN>;
close FILEIN;
定期使用样板。现在,我使用File::Slurp
表示我想要完全保存在内存中的小文件,Tie::File
表示我想要可扩展的大文件和/或我想要更改的文件。
答案 8 :(得分:3)
使用单行
将整个文件$文件读入变量$ text$text = do {local(@ARGV, $/) = $file ; <>};
或作为一种功能
$text = load_file($file);
sub load_file {local(@ARGV, $/) = @_; <>}
答案 9 :(得分:2)
如果这些程序只是为了您的工作效率,那么无论如何都有效!根据您的需要构建尽可能多的错误处理。
如果整个文件很大,那么读取它可能不是长期执行的最佳方式,因此您可能希望在进入行时处理行而不是将它们加载到数组中。
我从The Pragmatic Programmer(Hunt&amp; Thomas)的其中一章中得到的一个提示是,您可能希望让脚本在切割和切割工作之前为您保存文件的备份。
答案 10 :(得分:2)
||
运算符具有更高的优先级,因此在将结果发送到“open”之前首先对其进行求值...在您提到的代码中,改为使用“或”运算符,您就不会'有这个问题。
open INPUT_FILE, "<$input_file"
or die "Can't open $input_file: $!\n";
答案 11 :(得分:1)
Damian Conway这样做:
$data = readline!open(!((*{!$_},$/)=\$_)) for "filename";
但我不建议你。