string 在 Perl 中将文件放入字符串的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/206661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to slurp a file into a string in Perl?
提问by dreeves
Yes, There's More Than One Way To Do Itbut there must be a canonical or most efficient or most concise way. I'll add answers I know of and see what percolates to the top.
是的,有不止一种方法可以做到,但必须有一种规范的或最有效或最简洁的方法。我会添加我知道的答案,看看有什么会渗透到顶部。
To be clear, the question is how best to read the contents of a file into a string. One solution per answer.
需要明确的是,问题是如何最好地将文件内容读入字符串。每个答案一个解决方案。
回答by Leon Timmermans
How about this:
这个怎么样:
use File::Slurp;
my $text = read_file($filename);
ETA: note Bug #83126 for File-Slurp: Security hole with encoding(UTF-8). I now recommend using File::Slurper(disclaimer: I wrote it), also because it has better defaults around encodings:
ETA:注意File-Slurp 的错误 #83126:带有编码的安全漏洞(UTF-8)。我现在推荐使用File::Slurper(免责声明:我写的),也是因为它在编码方面有更好的默认值:
use File::Slurper 'read_text';
my $text = read_text($filename);
or Path::Tiny:
use Path::Tiny;
path($filename)->slurp_utf8;
回答by brian d foy
I like doing this with a do
block in which I localize @ARGV
so I can use the diamond operator to do the file magic for me.
我喜欢用do
我本地化的块来做这个,@ARGV
这样我就可以使用菱形运算符为我做文件魔术。
my $contents = do { local(@ARGV, $/) = $file; <> };
If you need this to be a bit more robust, you can easily turn this into a subroutine.
如果您需要它更健壮一点,您可以轻松地将其转换为子程序。
If you need something really robust that handles all sorts of special cases, use File::Slurp. Even if you aren't going to use it, take a look at the source to see all the wacky situations it has to handle.File::Slurphas a big security problemthat doesn't look to have a solution. Part of this is its failure to properly handle encodings. Even my quick answer has that problem. If you need to handle the encoding (maybe because you don't make everything UTF-8 by default), this expands to:
如果您需要处理各种特殊情况的真正强大的东西,请使用File::Slurp。即使您不打算使用它,也可以查看源代码以了解它必须处理的所有古怪情况。File::Slurp有一个很大的安全问题,看起来没有解决方案。部分原因是它未能正确处理编码。即使我的快速回答也有这个问题。如果您需要处理编码(可能是因为默认情况下您没有将所有内容都设为 UTF-8),这将扩展为:
my $contents = do {
open my $fh, '<:encoding(UTF-8)', $file or die '...';
local $/;
<$fh>;
};
If you don't need to change the file, you might be able to use File::Map.
如果您不需要更改文件,则可以使用File::Map。
回答by Schwern
In writing File::Slurp(which is the best way), Uri Guttman did a lot of research in the many ways of slurping and which is most efficient. He wrote down his findings hereand incorporated them info File::Slurp.
在编写File::Slurp(这是最好的方法)时,Uri Guttman 对多种 slurping 方法进行了大量研究,哪种方法最有效。他在这里写下他的发现,并将它们合并到 File::Slurp 信息中。
回答by dreeves
open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);
回答by Tanktalus
Things to think about (especially when compared with other solutions):
需要考虑的事情(尤其是与其他解决方案相比时):
- Lexical filehandles
- Reduce scope
- Reduce magic
- 词法文件句柄
- 缩小范围
- 减少魔法
So I get:
所以我得到:
my $contents = do {
local $/;
open my $fh, $filename or die "Can't open $filename: $!";
<$fh>
};
I'm not a big fan of magic <> except when actually using magic <>. Instead of faking it out, why not just use the open call directly? It's not much more work, and is explicit. (True magic <>, especially when handling "-", is far more work to perfectly emulate, but we aren't using it here anyway.)
我不是魔法<>的忠实粉丝,除非实际使用魔法<>。与其伪造它,为什么不直接使用 open 调用呢?这不是更多的工作,而且是明确的。(真正的魔法<>,尤其是在处理“-”时,要完美地模拟要花费更多的工作,但无论如何我们都没有在这里使用它。)
回答by dwarring
mmap (Memory mapping) of strings may be useful when you:
当您执行以下操作时,字符串的 mmap(内存映射)可能会很有用:
- Have very large strings, that you don't want to load into memory
- Want a blindly fast initialisation (you get gradual I/O on access)
- Have random or lazy access to the string.
- May want to update the string, but are only extending it or replacing characters:
- 有非常大的字符串,您不想加载到内存中
- 想要一个盲目的快速初始化(你在访问时获得渐进的 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);
Update: May 2012
更新:2012 年 5 月
The following should be pretty well equivalent, after replacing Sys::Mmapwith File::Map
在用File::Map替换Sys::Mmap之后,以下内容应该非常等效
#!/usr/bin/perl
use warnings; use strict;
use File::Map qw{map_file};
map_file(my $str => '/tmp/words', '+<');
print substr($str, 100, 20);
回答by dwarring
use Path::Class;
file('/some/path')->slurp;
回答by zigdon
{
open F, $filename or die "Can't read $filename: $!";
local $/; # enable slurp mode, locally.
$file = <F>;
close F;
}
回答by moritz
This is neither fast, nor platform independent, and really evil, but it's short (and I've seen this in Larry Wall's code ;-):
这既不快,也不独立于平台,而且非常邪恶,但它很短(我在 Larry Wall 的代码中看到了这一点;-):
my $contents = `cat $file`;
Kids, don't do that at home ;-).
孩子们,不要在家里这样做;-)。
回答by Prakash K
use IO::All;
# read into a string (scalar context)
$contents = io($filename)->slurp;
# read all lines an array (array context)
@lines = io($filename)->slurp;