如何检查Perl中是否存在UTF-16文件名?

时间:2009-08-22 20:13:09

标签: perl utf-16

我有一个用UTF-16编码的文本文件。每行包含由制表符分隔的多个列。对于那些关心的人,该文件是从iTunes导出的播放列表TXT。第27列包含文件名。

我在Linux中使用Perl 5.8.8使用类似于以下代码的方式阅读它:

binmode STDIN, ":encoding(UTF-16)";
while(<>)
{
    chomp;
    my @cols = split /\t/, $_;
    my $filename = $cols[26];   # Column #27 contains the filename
    print "File exists!" if (-e "$filename");
}

(请注意:我已缩短此代码段。在我的实际代码中,我做了一些替换,将iTunes使用的绝对Windows文件名转换为在我的Linux机器上有效的文件名)

即使文件存在,( - e)文件测试也不会返回true。我认为这与UTF-16中的字符串有关,但无法弄清问题是什么。实际文件名仅使用ASCII字符。如果我打印$ filename变量,文件名就会正确打印。

Perl中的文件名可以是UTF16吗?有关如何使此代码段生效的任何想法吗?

3 个答案:

答案 0 :(得分:5)

UTF-16文本由:encoding层处理。当它进入$_时,没有办法告诉它曾经是UTF-16。我认为这不是你的问题。

我的猜测是你的文件名中有一些空格(当你尝试将其打印出来时没有注意到)或者你不在你认为的目录中。

尝试

if (-e $filename) { print "File exists!" } 
else { print "File <$filename> not found" }

并仔细检查文件名。您也可以use Cwd;打印出当前目录。

答案 1 :(得分:3)

我找到了解决方案:

第27列是最后一列,文件使用0d0a(\ r \ n)行结尾进行编码。 chomp只删除了0a(\ n)。不知道为什么我之前没有看到这个,但它与UTF16没有任何关系。

添加:

s/\r$//;

在chomp修复问题之后。

感谢您的帮助 - 抱歉让您沿着兔子路走下去。

答案 2 :(得分:2)

如果您说,实际文件名仅使用ASCII字符,则不会

$filename =~ s/\0//g;

工作?无论如何,xxd应该在下次遇到类似这样的事情时提供帮助

[sinan@archardy ~]$ xxd /mnt/c/Documents\ and\ Settings/sinan/Desktop/test.txt
0000000: fffe 2f00 6800 6f00 6d00 6500 2f00 7300  ../.h.o.m.e./.s.
0000010: 6900 6e00 6100 6e00 2f00 7400 6500 7300  i.n.a.n./.t.e.s.
0000020: 7400 6d00 6500 2e00 7400 7800 7400 0d00  t.m.e...t.x.t...
0000030: 0a00                                     ..

我发现您在创建测试文件并重启到Linux时花了很长时间才解决了问题。哦,好吧。