阅读后写文件最有效的方法

时间:2014-08-05 19:37:08

标签: perl file-io

我正在读取文件中的一些数据,对其进行操作,然后将其覆盖到同一文件中。到现在为止,我一直这样做:

open (my $inFile, $file) or die "Could not open $file: $!";

    $retString .= join ('', <$inFile>); 
    ...

close ($inFile);

open (my $outFile, $file) or die "Could not open $file: $!";

    print $outFile, $retString;

close ($inFile);

但是我意识到我可以使用truncate函数并打开文件进行读/写:

open (my $inFile, '+<', $file) or die "Could not open $file: $!";

    $retString .= join ('', <$inFile>); 
    ...
    truncate $inFile, 0;
    print $inFile $retString;

close ($inFile);

我在任何地方都没有看到任何这样的例子。它似乎运作良好,但我做得对吗?有更好的方法吗?

4 个答案:

答案 0 :(得分:2)

读取整个文件内容的规范方法是(暂时)将输入记录分隔符 $/设置为undef,之后是下一个readline将返回文件的所有其余部分。但我认为你的原始技术比重新打开文件更清晰,更少参与。

请注意,以下所有示例均使用autodie pragma,这样就无需明确测试openclosetruncate,{{}的状态1}},以及此处未使用的许多其他相关调用。

以读/写模式打开并使用truncate将如下所示

seek

而简单的第二次打开将是

use strict;
use warnings;
use autodie;

use Fcntl 'SEEK_SET';

my ($file) = @ARGV;

open my $fh, '+<', $file;
my $ret_string = do { local $/; <$fh>; };

# Modify $ret_string;

seek $fh, 0, SEEK_SET;
truncate $fh, 0;
print $fh $ret_string;
close $fh;

还有第三种方法,即使用等效的 edit-in-place use strict; use warnings; use autodie; my ($file) = @ARGV; open my $fh, '<', $file; my $ret_string = do { local $/; <$fh>; }; # Modify $ret_string; open $fh, '>', $file; print $fh $ret_string; close $fh; 命令行选项。如果将内置变量-i设置为$^I以外的任何值,并将命令行上的文件传递给程序,则Perl将通过附加值undef透明地重命名并打开一个带有原始名称的新输出文件。

如果将$^I设置为空字符串$^I,则原始文件将从目录中删除,并在关闭时消失(请注意,Windows不支持此功能,并且你指定一个非空值)。但是,当您测试代码时,最好将其设置为其他内容,以便在成功销毁数据时有一条撤退的路径。

该模式看起来像这样

''

请注意,新输出文件被选为默认输出,如果要打印到控制台,则必须编写明确的use strict; use warnings; $^I = '.old'; my $ret_string = do { local $/; <>; }; # Modify $ret_string; print $ret_string;

答案 1 :(得分:2)

我建议使用$INPLACE_EDIT

use strict;
use warnings;

my $file = '...';

local @ARGV = $file;
local $^I = '.bak';
while (<>) {
    # Modify the line;
    print;
}
# unlink "$file$^I"; # Optionally delete backup

有关编辑文件的其他方法,请阅读perlfaq5 - How do I change, delete, or insert a line in a file, or append to the beginning of a file?

答案 2 :(得分:1)

我会改变您阅读文件的方式,而不是如何打开文件。连接线的效率低于一次读取整个文件的效率,

 $retString .= do { local $/; <$inFile> };

对于truncate,您可能希望首先尝试将文件作为perldoc suggests

开始
  

FILEHANDLE文件中的位置保持不变。您可能希望在写入文件之前调用seek。

答案 3 :(得分:1)

如果要更改文件中的某些行,Tie::File模块可能会有所帮助。

喜欢这个

use strict;
use warnings;

use Tie::File;

tie my @source, 'Tie::File', 'file.txt' or die $!;

for my $line (@source) {
   # Modify $line here      
}

untie @source;