2012-09-05 33 views
0

当我运行下面的脚本,我得到这样一个腐败的YAML文件,以便这为什么会损坏我的yaml文件?

--- 
1: 
    name1: abc 
    name2: abc 
--- 
me3: abc 
--- 

问题

任何人都可以看到,我做错了什么?

#!/usr/bin/perl 

use strict; 
use YAML::Syck; 
use Fcntl ':flock', 'SEEK_SET'; 
use warnings; 
use Data::Dumper; 

my $acc; 
my $acc_fh; 

$acc->{1}{name1} = "abc"; 

unlink 'test.yaml'; 

# write initial 
open F, '>', 'test.yaml'; 
print F YAML::Syck::Dump($acc); 
close F; 


($acc, $acc_fh) = read_yaml_with_lock('test.yaml'); 
$acc->{1}{name2} = "abc"; 
$acc->{1}{name3} = "abc"; 
write_yaml_with_lock($acc, $acc_fh); 

($acc, $acc_fh) = read_yaml_with_lock('test.yaml'); 
delete $acc->{1}{name3}; 
write_yaml_with_lock($acc, $acc_fh); 


sub read_yaml_with_lock { 
    my ($file) = @_; 

    open my $fh, '+<', $file or die $!; 
    flock($fh, LOCK_EX) or die $!; 

    my $obj = YAML::Syck::LoadFile($fh); # this dies on failure 
    return ($obj, $fh); 
} 

sub write_yaml_with_lock { 
    my ($obj, $fh) = @_; 

    my $yaml = YAML::Syck::Dump($obj); 
    $YAML::Syck::ImplicitUnicode = 1; 
    seek $fh, 0, SEEK_SET; # seek back to the beginning of file 

    print $fh $yaml . "---\n"; 
    close $fh; 
} 

回答

3

您将两次写入同一文件。在第二次你写的YAML代码比第一次短,因为你删除了调用之间的哈希键。但是,您在第一次之后既没有unlink文件也没有truncate它在第二次写入之后。所以,你看到的腐败是第一次写入的文件的一部分,但第二次没有被覆盖。

+0

我明白了。我只是觉得,文件大小会适应。你会如何做出正确的“截断”? –

+0

两种可能性:截断为0,之后写入(不需要在这种情况下寻找),或者之后查找,写入并截断到当前文件位置。 –

+0

所以你的意思是'truncate($ fh,tell $ fh)'? –

3

"me3"部分是" name3"的剩余部分,其被"---\n"(4个字符)部分覆盖。当你第一次写,你有更多的数据。然后你倒回文件句柄位置并写出一个较短的数据,它不覆盖所有旧数据。

我认为你的解决方案“应该”是跳过这个传递文件句柄并倒带它,而是为每个子例程使用适当的open。例如: -

sub read_yaml { 
    my $file = shift; 
    open my $fh, '<', $file or die $!; 
    ... 
    close $fh; 
} 

sub write_yaml { 
    my ($file, $obj) = @_; 
    open my $fh, '>', $file or die $!; 
    ... 
    close $fh; 
} 

保持文件处理操作不是真的那么有用或有效率之间打开,并介绍了一些困难。

+0

解决方案是用'truncate($ fh,0);'替换'seek $ fh,0,SEEK_SET;'? –

+0

@SandraSchlichting当你用'+ <'mode'seek''玩弄时,你会让自己变得更加困难。与关闭文件并重新打开文件相比,您不会节省(很多)时间。所以我的建议是以截断模式重新打开文件。 – TLP

+0

我有点迷路了。如何以截断模式打开文件? –

相关问题