【问题标题】:How do I read the contents of a small text file into a scalar in Perl?如何在 Perl 中将小文本文件的内容读入标量?
【发布时间】:2017-04-21 23:08:56
【问题描述】:

我有一个小文本文件,我想将它读入一个与文件中完全相同的标量变量(保留行分隔符和其他空格)。

Python 中的等价物类似于

buffer = ""

try:
    file = open("fileName", 'rU')
    try:
        buffer += file.read()
    finally:
        file.close()
except IOError:
    buffer += "The file could not be opened."

这是为了简单地在网页上重新显示文件的内容,这就是为什么我的错误消息会进入我的文件缓冲区的原因。

【问题讨论】:

    标签: perl file-io


    【解决方案1】:

    来自Perl Cookbook

    my $filename = 'file.txt';
    open( FILE, '<', $filename ) or die 'Could not open file:  ' . $!;
    
    undef $/;
    my $whole_file = <FILE>;
    

    我会本地化更改:

    my $whole_file = '';
    {
        local $/;
        $whole_file = <FILE>;
    }
    

    【讨论】:

    • 你的方法更好。来自我的 +1 :)
    • Perl Cookbook 对于我的 Perl 知识水平来说有点高级。我将在哪里以及如何将文件句柄设置为我的文件名?我如何处理错误? “= q{}”是做什么的?
    • 抱歉,让我调整一下以显示文件句柄。而 q{some text} 只是做单引号的一种奇特方式。为了清楚起见,我将其删除。
    • 感谢您耐心编辑此答案以向我展示更多详细信息。我真的很感激。
    • 绝对本地化 $/ 变量,否则你会炸毁你在别处的阅读。
    【解决方案2】:

    作为亚历克斯所说的替代方案,您可以install File::Slurp 模块(来自命令行的cpan -i File::Slurp)并使用它:

    use File::Slurp;
    # Read data into a variable
    my $buffer = read_file("fileName");
    # or read data into an array
    my @buffer = read_file("fileName");
    

    请注意,这个dies(嗯...croaks,但这只是从模块中调用 die 的正确方法)出现错误,因此您可能需要在 eval 块中运行它以捕获任何错误。

    【讨论】:

    • 我只想补充一点,对于大多数 Perl 程序员来说,这可能是最好的解决方案。我应该在问题中这么说,但我正在使用嵌入式设备,所以我被限制安装任何超过严格必要的模块。
    【解决方案3】:

    如果我附近没有SlurpPerl6::Slurp,那么我通常会选择....

    open my $fh, '<', 'file.txt' or die $!;
    
    my $whole_file = do { local $/; <$fh> };
    

    【讨论】:

    • 同意,这比目前接受的答案要好得多,而且更现代/简洁。
    【解决方案4】:

    讨论了读取文件here的各种方法。

    【讨论】:

      【解决方案5】:

      我没有足够的声誉来发表评论,所以我很抱歉再次发帖。

      @Harold Bamford:对于 Perl 程序员来说,$/不应该是一个不起眼的变量。初学者可能不知道它,但他或她应该学习它。由于上面 hackingwords 链接的文章中所述的原因,join 方法是一个糟糕的选择。以下是文章的相关引述:

      这不必要地将输入文件分成几行(join 为 提供了一个列表上下文),然后再次连接这些行。这个习语的原始编码器显然从未读过 perlvar 并学会了如何使用 $/ 来允许标量 slurping。

      【讨论】:

        【解决方案6】:

        你可以这样做:

        $data_file="somefile.txt";
        open(DAT, $data_file);
        @file_data = <DAT>;
        close(DAT);
        

        这将为您提供数组中的文件内容,您可以将其用于您想要的任何内容,例如,如果您想要每一行,您可以执行以下操作:

        foreach $LINE (@file_data)
        {
            dosomethingwithline($LINE);
        }
        

        完整的用法示例:

        my $result;
        $data_file = "somefile.txt";
        my $opened = open(DAT, $data_file);
        if (!$opened)
        {
            $result = "Error.";
        }
        else
        {
            @lines = <DAT>;
            foreach $LINE (@lines)
            {
                $result .= $LINE;
            }
            close(DAT);
        }
        

        然后您可以根据需要使用$result。注意:此代码未经测试,但它应该给你一个想法。

        【讨论】:

        • 要将结果放入标量中,您可以这样做: my $text = join( "\n", @file_data ); ## 未经测试
        • 感谢编辑显示错误处理。这对 Perl 新手很有帮助。
        • gpojd - 你应该用 "" 而不是 "\n" 加入它们,因为我们从来没有 chomp() 过它们,所以它们最后已经有一个 "\n"。基本上:我的 $text = join("", );应该可以工作(未经测试)。
        • 其实是别人比我更胜一筹。哦,好吧,没关系。
        【解决方案7】:

        我会像这样调整 draegtun 的答案,以使其完全按照要求进行:

        my $buffer;
        if ( open my $fh, '<', 'fileName' ) {
            $buffer = do { local $/; <$fh> };
            close $fh;
        } else {
            $buffer = 'The file could not be opened.';
        }
        

        【讨论】:

          【解决方案8】:

          只需将所有行连接成一个字符串:

          open(F, $file) or die $!;
          my $content = join("", <F>); 
          close F;
          

          (之前建议使用 join "\n" 但这会添加额外的换行符。每行在读取时已经在其末尾有一个换行符。)

          【讨论】:

          • 这首先将其分成几行,然后将这些行重新连接起来。不好。
          • 它满足了提问者的明显需求。这很容易理解。它几乎与迄今为止评分最高的答案相同。而且它不需要像 $/ 这样的晦涩的项目知识。我在这里没有看到问题
          • $/ 并不晦涩。 ;-) 问题是这个例子不是惯用的或高效的 Perl。接受的答案更好。
          • $/ 对于 Perl 初学者来说是晦涩难懂的。我只是没有看到这个答案应该被降级。我同意接受的答案在所有方面都更好。可能最好的部分是对 Perl Cookbook 的引用。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-04
          • 2011-03-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多