使用Perl中的Path :: Tiny读取txt文件时出错

时间:2016-05-26 20:37:30

标签: perl

我想使用Path::Tiny模块来阅读一些文本文件。

我创建了我想要在文件list.txt中读取的文件名列表,但是当我运行我的代码时,我收到此错误消息

Error open <<:raw:encoding<UTF-8>> on '[thefirstfilenames.txt]': Invalid argument at Test2.PL line 15.

我的代码如下:

use strict;
use 5.010;
use warnings;

use Path::Tiny qw(path); # http://perlmaven.com/use-path-tiny-to-read-and-write-file

my $file = "list.txt";
open (FH, "< $file") or die "Can't open $file for read: $!";
my @list = <FH>;
close FH or die "Cannot close $file: $!"; 

my $size = @list;

for ( my $i = 0; $i < $size; $i++ ) {
    my $filename = "$list[$i]";
    my $content = path($filename)->slurp_utf8;
    print "$content\n";
}

这有什么解决方案吗?当我手动逐个放置文件名时,它工作正常。

2 个答案:

答案 0 :(得分:3)

我不确定您如何将Invalid argumentEINVAL)视为错误,但是从错误消息中可以清楚地看到文件中的行包含{{{{{{ 1}}括号。这可能不是有效的文件名,您需要从文件或程序中删除它们。

Buuut ...我怀疑你没有向我们展示真正的错误信息,在寻求调试帮助时非常重要。我怀疑你得到的是这样的东西,换行和所有。

[thefirstfilenames.txt]

当您从文件中读取时,每行仍然有一个换行符。你需要删除它。这通常使用chomp完成,可以一次完成整个列表。

还可以采取其他措施来改进代码。由于您已经在使用Path :: Tiny,请通过调用Path::Tiny->lines替换程序的开头。并称之为:Error open <<:raw:encoding<UTF-8>> on 'somefilename.txt ': Invalid argument at Test2.PL line 15.

@filenames

最重要的是摆脱C风格的循环和let Perl iterate through the @filenames

my @filenames = path($file)->lines_utf8;
chomp @filenames;

答案 1 :(得分:1)

主要问题是您不会从list.txt读取的文件名末尾删除不需要的字符。这意味着$filename的每个值仍然会包含在方括号[ ... ]中,并且附加了一个不需要的"\n",您应该将其删除

这是重写你自己的代码来解决这个问题。它还纠正了一些老式的技术,例如使用词法文件句柄三参数形式的open ,并迭代内容<{em>} @list而非其索引

use strict;
use warnings;

use Path::Tiny 'path';

my $file = 'list.txt';

my @files = do {
    open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
    map { / \[ ( [^\[\]]+ ) \] /x } <$fh>;
};

for my $file ( @files) {
    my $content = path($file)->slurp_utf8;
    print $content, "\n";
}

这对你有用,但在我看来Path::Tiny在这里是不必要的,slurp_utf8在Windows行结尾中保留了CR字符,这不是标准的Perl行为,可能不是想要的。使用do块打开文件并本地化$/可以很容易地进行啜食。它的优势在于所有内容都是在标准Perl中完成的,任何阅读它的人都不必猜测path($file)->slurp_utf8可能会做什么(这显然不是你所期望的直接啜泣)。喜欢这个

use strict;
use warnings;

my $file = 'list.txt';

my @files = do {
    open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
    <$fh>;
};
chomp @files;

for my $file ( @files) {

    my $content = do {
        open my $fh, '<:encoding(utf-8)', $file or die qq{Unable to open "$file" for input: $!};
        local $/;
        <$fh>;
    };

    print $content, "\n";
}