如何检查Perl中是否存在UTF-16文件名?
我有一个以UTF-16编码的文本文件。每行包含多个由制表符分隔的列。对于那些关心,该文件是从iTunes导出的播放列表TXT。列#27包含一个文件名。如何检查Perl中是否存在UTF-16文件名?
我使用类似的代码在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");
}
(请注意:我已经缩短这个代码片断在我实际的代码中,我做了一些换人转换。绝对windows文件名由iTunes用于在我的Linux机器上有效的文件名)
即使文件存在,(-e)文件测试也不会返回true。我相信它与UTF-16中的字符串有关,但无法弄清楚问题所在。实际的文件名只使用ASCII字符。如果我打印$ filename变量,文件名打印正确。
Perl中的文件名可以使用UTF16吗?任何想法如何让这段代码片段工作?
UTF-16文本由编码层处理。当它进入$_
时,无法告诉它它曾经是UTF-16。我不认为这是你的问题。
我的猜测是你的文件名中有一些空格(当你试图打印出来时你没有注意到),或者你不在自己认为的目录中。
尝试
if (-e $filename) { print "File exists!" }
else { print "File <$filename> not found" }
,并仔细检查文件名。您也可以use Cwd;
并打印出当前目录。
谢谢cjm:我在发布我的解决方案后看到了这个,但你是对的。 – blt04 2009-08-22 20:54:07
如果像你说的,实际文件名只使用ASCII字符,不会
$filename =~ s/\0//g;
工作?无论如何,xxd
应该帮助你碰上这样的事情
[[email protected] ~]$ 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上的时间解决你的问题的下一次。好吧。
我想出溶液:
柱27是最后一列,并且该文件被编码有0D0A(\ r \ n)的行尾。 chomp只能删除0a(\ n)。不知道为什么我之前没有看到它,但它与UTF16没有任何关系。
添加:
s/\r$//;
格格后解决了这个问题。
感谢您的帮助 - 对不起,送你一只兔子踪迹。
在我花费任何时间之前,什么是'my $ filename =〜$ cols [26];'? – 2009-08-22 20:15:54
抱歉 - 错字。应该是=在StackOverflow错字,而不是我原来的代码。问题依然存在。 – blt04 2009-08-22 20:17:22
文件名本身不能是UTF-16,因为UTF-16填满了零字节。现在许多Linux发行版正在使用UTF-8,所以这将是第一个尝试的编码。 – bobince 2009-08-22 20:46:47