在Perl中将文件粘贴到字符串中的最佳方法是什么?

时间:2008-10-15 21:55:47

标签: perl string file-io file

是的,There's More Than One Way To Do It但必须有规范或最有效或最简洁的方式。我会添加我知道的答案,看看有什么渗透到顶部。

要清楚,问题是如何最好地将文件内容读入字符串。 每个答案一个解决方案。

17 个答案:

答案 0 :(得分:70)

这个怎么样:

use File::Slurp;
my $text = read_file($filename);

ETA:注意Bug #83126 for File-Slurp: Security hole with encoding(UTF-8)。我现在建议使用File::Slurper(免责声明:我写了它),也因为它有更好的编码默认值:

use File::Slurper 'read_text';
my $text = read_text($filename);

Path::Tiny

use Path::Tiny;
path($filename)->slurp_utf8;

答案 1 :(得分:44)

我喜欢使用do块进行本地化@ARGV,因此我可以使用菱形运算符为我执行文件魔术。

 my $contents = do { local(@ARGV, $/) = $file; <> };

如果您需要更强大一些,可以轻松将其转换为子程序。

如果您需要能够处理各种特殊情况的强大功能,请使用File::Slurp。即使您不打算使用它,也要查看源代码以查看它必须处理的所有古怪情况。 File::Slurpbig security problem不看有一个解决方案。部分原因是它无法正确处理编码。即使我的快速回答也有这个问题。如果你需要处理编码(可能是因为你没有默认设置UTF-8),这会扩展为:

my $contents = do {
    open my $fh, '<:encoding(UTF-8)', $file or die '...';
    local $/;
    <$fh>;
    };

如果您不需要更改文件,则可以使用File::Map

答案 2 :(得分:35)

在编写File::Slurp(这是最好的方式)时,Uri Guttman在许多啜饮方式方面进行了大量研究,效率最高。他写下了his findings here并将它们合并为信息文件:: Slurp。

答案 3 :(得分:20)

open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);

答案 4 :(得分:11)

要考虑的事情(特别是与其他解决方案相比):

  1. Lexical filehandles
  2. 缩小范围
  3. 减少魔法
  4. 所以我得到了:

    my $contents = do {
      local $/;
      open my $fh, $filename or die "Can't open $filename: $!";
      <$fh>
    };
    

    我不是魔术的忠实粉丝&lt;&gt;除非实际使用魔法&lt;&gt;。而不是假装,为什么不直接使用公开电话?这不是更多的工作,而是明确的。 (真正的魔法&lt;&gt;,特别是在处理“ - ”时,要完美地模仿,还有更多工作要做,但我们无论如何都不在这里使用它。)

答案 5 :(得分:10)

当您执行以下操作时,

字符串的mmap(内存映射)可能很有用:

  • 有非常大的字符串,您不想加载到内存中
  • 想要盲目快速初始化(在访问时获得渐进的I / O)
  • 对字符串进行随机或延迟访问。
  • 可能想要更新字符串,但只是扩展它或替换字符:
#!/usr/bin/perl
use warnings; use strict;

use IO::File;
use Sys::Mmap;

sub sip {

    my $file_name = shift;
    my $fh;

    open ($fh, '+<', $file_name)
        or die "Unable to open $file_name: $!";

    my $str;

    mmap($str, 0, PROT_READ|PROT_WRITE, MAP_SHARED, $fh)
      or die "mmap failed: $!";

    return $str;
}

my $str = sip('/tmp/words');

print substr($str, 100,20);

更新:2012年5月

在用Sys::Mmap

替换File::Map之后,以下内容非常相同
#!/usr/bin/perl
use warnings; use strict;

use File::Map qw{map_file};

map_file(my $str => '/tmp/words', '+<');

print substr($str, 100, 20);

答案 6 :(得分:8)

use Path::Class;
file('/some/path')->slurp;

答案 7 :(得分:7)

{
  open F, $filename or die "Can't read $filename: $!";
  local $/;  # enable slurp mode, locally.
  $file = <F>;
  close F;
}

答案 8 :(得分:5)

use IO::All;

# read into a string (scalar context)
$contents = io($filename)->slurp;

# read all lines an array (array context)
@lines = io($filename)->slurp;

答案 9 :(得分:4)

查看Perl6::Slurp的摘要,它非常灵活,通常只需很少的努力即可做到正确。

答案 10 :(得分:4)

这既不快,也不与平台无关,而且非常邪恶,但它很短(我在Larry Wall的代码中看到了这一点; - ):

 my $contents = `cat $file`;

孩子,不要在家里这样做; - )。

答案 11 :(得分:3)

答案 12 :(得分:3)

没有人说过有关read或sysread的内容,所以这里有一个简单快捷的方法:

my $string;
{
    open my $fh, '<', $file or die "Can't open $file: $!";
    read $fh, $string, -s $file;   # or sysread
    close $fh;
}

答案 13 :(得分:3)

对于单行,您通常可以使用the -0 switch(使用-n)使perl立即读取整个文件(如果文件不包含任何空字节):

perl -n0e 'print "content is in $_\n"' filename

如果是二进制文件,您可以使用-0777

perl -n0777e 'print length' filename

答案 14 :(得分:1)

候选人做最糟糕的方式! (见评论。)

open(F, $filename) or die "OPENING $filename: $!\n";
@lines = <F>;
close(F);
$string = join('', @lines);

答案 15 :(得分:0)

调整特殊记录分隔符变量$/

undef $/;
open FH, '<', $filename or die "$!\n";
my $contents = <FH>;
close FH;

答案 16 :(得分:-1)

# Takes the name of a file and returns its entire contents as a string.
sub getfile 
{
  my($filename) = @_;
  my($result);

  open(F, $filename) or die "OPENING $filename: $!\n";
  while(<F>) { $result .= $_; }
  close(F);

  return $result;
}