2009-08-22 59 views
4

我有一个以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吗?任何想法如何让这段代码片段工作?

+1

在我花费任何时间之前,什么是'my $ filename =〜$ cols [26];'? – 2009-08-22 20:15:54

+0

抱歉 - 错字。应该是=在StackOverflow错字,而不是我原来的代码。问题依然存在。 – blt04 2009-08-22 20:17:22

+0

文件名本身不能是UTF-16,因为UTF-16填满了零字节。现在许多Linux发行版正在使用UTF-8,所以这将是第一个尝试的编码。 – bobince 2009-08-22 20:46:47

回答

5

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

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

尝试

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

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

+0

谢谢cjm:我在发布我的解决方案后看到了这个,但你是对的。 – blt04 2009-08-22 20:54:07

2

如果像你说的,实际文件名只使用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上的时间解决你的问题的下一次。好吧。

+0

你会想。但事实并非如此。 -e仍然返回false。 只是为了测试我的代码的其余部分,我试图在Perl文件中硬编码一个文件名,并且它工作。从iTunes UTF16文件读取(即使使用您的空替换建议)也不起作用。 – blt04 2009-08-22 20:24:35

+0

尝试utf8:在空替换之前降级($ filename)。 – Inshallah 2009-08-22 20:30:22

+0

@Inshalla:仍然不起作用。 – blt04 2009-08-22 20:33:14

3

我想出溶液:

柱27是最后一列,并且该文件被编码有0D0A(\ r \ n)的行尾。 chomp只能删除0a(\ n)。不知道为什么我之前没有看到它,但它与UTF16没有任何关系。

添加:

s/\r$//; 

格格后解决了这个问题。

感谢您的帮助 - 对不起,送你一只兔子踪迹。

+1

所以我说得对,这是你的文件名中的空格:-) – cjm 2009-08-22 20:54:38

+0

你也可以尝试':crlf:encoding(UTF-16)',尽管我从来没有试过用UTF-16的crlf,所以我不是当然,如果这有效。我只使用了:带有单字节编码的crlf。 – cjm 2009-08-22 20:56:21

相关问题