2010-08-17 69 views
3

我试图读取与下面的代码的二进制文件:使用ActivePerl读取二进制文件的问题?

open(F, "<$file") || die "Can't read $file: $!\n"; 
binmode(F); 
$data = <F>; 
close F; 

open (D,">debug.txt"); 
binmode(D); 
print D $data; 
close D; 

输入文件是16M; debug.txt只有大约400k。当我查看emacs中的debug.txt时,最后两个字符是^ A^C(根据记事本++,SOH和ETX字符),尽管debug.txt中存在相同的模式。文件中的下一行确实有一个^ O(SI)字符,我认为这是该特定字符的第一次出现。

我该如何阅读整个文件?

+0

$ data = ;获取$ data = do {undef $ /; }; – 2010-08-17 13:34:24

回答

5

如果你真的想要一次读取整个文件,请使用slurp模式。可以通过将$/(这是输入记录分隔符)设置为undef来开启Slurp模式。这最好在一个单独的块中完成,因此您不要为其他代码搞砸$/

my $data; 
{ 
    open my $input_handle, '<', $file or die "Cannot open $file for reading: $!\n"; 
    binmode $input_handle; 
    local $/; 
    $data = <$input_handle>; 
    close $input_handle; 
} 

open $output_handle, '>', 'debug.txt' or die "Cannot open debug.txt for writing: $!\n"; 
binmode $output_handle; 
print {$output_handle} $data; 
close $output_handle; 

使用my $data为一个全局变量词法和our $data

+1

编辑为了促进现代实践,请参阅[为什么三个参数打开电话与词法文件句柄Perl最佳实践?](http://stackoverflow.com/questions/1479741/why-is-three-argument-开放调用与词法文件句柄一个perl最佳实践)和[什么是在Perl中打开和读取文件的最佳方式?](http://stackoverflow.com/questions/318789/whats-the -best路到开和读取一个文件 - 在-perl的)。 – daxim 2010-08-17 13:53:10

+0

@daxim - 我想提出检查,但我觉得这是O​​P自己的责任...... :) – MvanGeest 2010-08-17 13:53:57

+1

如果没有领导好的榜样和根除过时的代码,我们不能教导。 :) – daxim 2010-08-17 14:06:46

3

TIMTOWTDI

File::Slurp是表达你想达到的最短的方式。它也有内置的错误检查。

use File::Slurp qw(read_file write_file); 
my $data = read_file($file, binmode => ':raw'); 
write_file('debug.txt', {binmode => ':raw'}, $data); 

IO::File API更优雅时尚解决全局变量$/问题。

use IO::File qw(); 
my $data; 
{ 
    my $input_handle = IO::File->new($file, 'r') or die "could not open $file for reading: $!"; 
    $input_handle->binmode; 
    $input_handle->input_record_separator(undef); 
    $data = $input_handle->getline; 
} 
{ 
    my $output_handle = IO::File->new('debug.txt', 'w') or die "could not open debug.txt for writing: $!"; 
    $output_handle->binmode; 
    $output_handle->print($data); 
} 
+0

不要太在意高雅 - 这是一个快速&肮脏的解决方案。但感谢您的教育。 – chris 2010-08-17 14:24:19

+0

在第二个例子中,你为什么要将块本地化? – jmcnamara 2010-09-17 12:05:35

+0

当句柄变量超出范围时,附加的文件描述符会自动关闭。裸块是创建这种范围最直接的方法。 – daxim 2010-09-17 12:33:11

0

我不认为这是关于使用slurp模式或不是,而是关于正确处理二进制文件。

代替

$data = <F>; 

你应该做的

read(F, $buffer, 1024); 

这将只读取1024个字节,所以你必须增加缓冲或使用循环的一部分读取整个文件的一部分。