我正在读取文件中的一些数据,对其进行操作,然后将其覆盖到同一文件中。到现在为止,我一直这样做:
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);
我在任何地方都没有看到任何这样的例子。它似乎运作良好,但我做得对吗?有更好的方法吗?
答案 0 :(得分:2)
读取整个文件内容的规范方法是(暂时)将输入记录分隔符 $/
设置为undef
,之后是下一个readline
将返回文件的所有其余部分。但我认为你的原始技术比重新打开文件更清晰,更少参与。
请注意,以下所有示例均使用autodie
pragma,这样就无需明确测试open
,close
,truncate
,{{}的状态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;