代码之家  ›  专栏  ›  技术社区  ›  blt04

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

  •  4
  • blt04  · 技术社区  · 15 年前

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

    我在Linux中使用Perl5.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 回复  |  直到 15 年前
        1
  •  5
  •   cjm    15 年前

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

    我猜可能是你的文件名中有一些空白(当你尝试打印时没有注意到),或者你不在你认为的目录中。

    尝试

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

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

        2
  •  3
  •   blt04    15 年前

    我想出了解决办法:

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

    添加:

    s/\r$//;
    

    在Chomp解决了问题之后。

    谢谢你的帮助-很抱歉送你去一条兔子的小路。

        3
  •  2
  •   Sinan Ünür    15 年前

    如您所说,如果实际文件名仅使用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时,您已经解决了您的问题。哦,好吧。