2008-11-25 80 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"; 
相關問題