2008-11-25 53 views
43

请注意 - 我不是在寻找打开/读取文件的“正确”方式,也不是每次打开/读取文件的方式。我只是想了解大多数人使用什么方式,并且可能同时学习一些新方法:)*在Perl中打开和读取文件的最佳方式是什么?

我的Perl程序中一个非常常见的代码块是打开文件并读取或写入它。我已经看到了很多这样做的方式,而且我多年来一直致力于完成这项任务。我只是想知道什么最好(如果有最好的方法)的方法是做到这一点?

我用来打开这样的文件:

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

[peropentut](http://perldoc.perl.org/perlopentut.html)手册页涵盖了这个问题的大部分内容。 – converter42 2008-11-25 20:56:16

回答

58

有没有通用的标准,但有理由选择一个或另一个。我首选的形式是这样的:

open(my $input_fh, "<", $input_file) || die "Can't open $input_file: $!"; 

的原因是:

  • 您立即报告错误。 (如果这是你想要的,用“警告”替换“死亡”。)
  • 你的文件句柄现在是引用计数的,所以一旦你不使用它,它将被自动关闭。如果使用全局名称INPUT_FILEHANDLE,则必须手动关闭文件,否则它将保持打开状态,直到程序退出。
  • 读取模式指示符“<”与$ input_file分开,增加了可读性。

下面是巨大的,如果该文件是小,你知道你想要的所有行:

my @lines = <$input_fh>; 

你甚至可以做到这一点,如果你需要处理的所有行作为一个字符串:

my $text = join('', <$input_fh>); 

对于长文件,您将希望用while迭代行,或者使用read。

+0

或略有变化...打开我的$ input_fh,'<',$ input_file或死“无法打开$ input_file:$!”; – draegtun 2008-11-25 22:34:09

+2

我仍然认为这是样板。只需使用`File :: Slurp`或`Tie :: File`即可。 – Svante 2008-11-29 13:11:55

+0

__Nice编辑tof! – monksy 2013-02-22 22:10:24

14

如果你想整个文件作为一个字符串,就没有必要来遍历它。

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这里还没有定义,但其余的是犹太教。

+0

本地$ RS = undef;做? – 2012-11-06 20:52:35

+2

`$ RS`与``/```'英语`为您设置的'$ /`相同。 `$ /`是跟踪`<$fh>`的行分隔符值的变量,它与`get-line`或$ fh-> getline()`的概念同义。实质上,它包含内部读取算法用于知道何时读取完整“数据行”的值,并将其设置为“undef”意味着“没有指示全行的标记”,因此它读取整体文件作为“行” – 2012-11-18 08:15:07

2

如果这些程序只是为了您的工作效率,无论什么作品!建立尽可能多的错误处理,你认为你需要。

读入整个文件,如果是大的未必是最好的方式长期做的事情,所以你可能需要处理线,因为他们进来,而不是在一个数组装载它们。

我从实用程序员(Hunt & Thomas)的一个章节中得到的一个提示是,在开始工作切片和切块之前,您可能希望让脚本为您保存文件的备份。

11

如果文件足够小,阅读了整个事情到内存中是可行的,使用File::Slurp。它使用一个非常简单的API读取和写入完整的文件,并且执行所有错误检查,因此您不必这样做。

6

有打开和读取文件没有最好的方式。这是一个错误的问题。文件中包含什么内容?在任何时候你需要多少数据?你一次需要所有的数据吗?你需要怎样处理这些数据?在考虑如何打开和读取文件之前,您需要先弄清楚这些问题。

是什么,你正在做的,现在给你造成的问题?如果不是,你有没有更好的问题要解决? :)

你的大部分问题仅仅是语法和Perl文档(特别是(perlopentut),你也可能会喜欢拿起Learning Perl,回答你们中的大多数在你的问题有问题,这是所有回答。

祝你好运:)

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; 
5

,有开在Perl文件中有

尽可能多的最好办法这是真的3210
$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(); 

买者讲师:这些都只是我的方法为日常工作致力于肌肉记忆,他们可能从根本上不适合你想要解决的问题。

4

我曾经经常使用的

open (FILEIN, "<", $inputfile) or die "..."; 
my @FileContents = <FILEIN>; 
close FILEIN; 

样板。现在,我使用File::Slurp的,我想完全在内存中举办小型的文件,为Tie::File,我想可伸缩的地址和/或我要到位,以改变文件大文件。

12

不得不写'或死亡,到处都驱使我坚果。我打开文件的首选方法是这样的:

use autodie; 

open(my $image_fh, '<', $filename); 

虽然这是很少打字,还有很多重要的事情要注意这是怎么回事:

  • 我们正在使用autodie编译指示,这意味着如果出现问题,所有Perl的内置函数都会抛出异常。它不需要在代码中编写or die ...,它会生成友好的,可读的错误消息,并且具有词汇范围。它可以从CPAN获得。

  • 我们使用的开放三个参数版本。这意味着,即使我们有一个包含字符,如<>|一个有趣的文件名,Perl会仍然做正确的事。在我的Perl安全 OSCON教程中,我展示了许多方法来让2参数open行为异常。本教程的注释可用于free download from Perl Training Australia

  • 我们使用标文件句柄。这意味着我们不会一致地关闭其他人的同名文件句柄,如果我们使用包文件句柄就会发生这种情况。这也意味着strict可以识别拼写错误,并且如果文件句柄超出范围,我们的文件句柄将自动清除。

  • 我们正在使用有意义的文件句柄。在这种情况下,它看起来像我们要写入一个图像。

  • 文件句柄与_fh结束。如果我们看到我们像使用普通标量那样使用它,那么我们知道这可能是一个错误。

3

阅读整个文件$文件到变量$文本与单行

$text = do {local(@ARGV, $/) = $file ; <>}; 

或作为功能

$text = load_file($file); 
sub load_file {local(@ARGV, $/) = @_; <>} 
1

达米安·康威的确是这样:

$data = readline!open(!((*{!$_},$/)=\$_)) for "filename"; 

但我不推荐给你。

2

||运算符具有更高的优先级,因此在将结果发送到“open”之前先进行评估......在您提到的代码中,请使用“或”运算符,而不是那样问题。

open INPUT_FILE, "<$input_file" 
    or die "Can't open $input_file: $!\n"; 
相关问题