Как я могу проверить наличие имен файлов UTF-16 в Perl?

У меня есть текстовый файл в кодировке UTF-16. Каждая строка содержит ряд столбцов, разделенных табуляцией. Для тех, кому не все равно, файл представляет собой экспортный TXT-файл плейлиста из iTunes. В столбце № 27 указано имя файла.

Я читаю его, используя Perl 5.8.8 в Linux, используя код, похожий на:

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) файла не возвращает истину. Я считаю, что это как-то связано со строкой в ​​UTF-16, но не могу понять, в чем проблема. В фактическом имени файла используются только символы ASCII. И имя файла печатается правильно, если я печатаю переменную $ filename.

Могут ли имена файлов в Perl быть в UTF16? Есть идеи, как заставить этот фрагмент кода работать?


person blt04    schedule 22.08.2009    source источник
comment
Прежде чем я займусь этим, что такое my $filename =~ $cols[26];?   -  person Sinan Ünür    schedule 23.08.2009
comment
извините - опечатка. Должно было быть = опечатка в StackOverflow, а не в моем исходном коде. Проблема осталась.   -  person blt04    schedule 23.08.2009
comment
Имена файлов не могут быть изначально UTF-16, потому что UTF-16 заполнен нулевыми байтами. Многие дистрибутивы Linux в наши дни используют UTF-8, так что это будет первая кодировка, которую нужно попробовать.   -  person bobince    schedule 23.08.2009


Ответы (3)


Текст UTF-16 обрабатывается уровнем: encoding. К тому времени, когда он попадает в $_, невозможно сказать, что это когда-либо был UTF-16. Я не думаю, что это твоя проблема.

Я предполагаю, что у вас либо есть пробелы в вашем имени файла (которые вы не заметили, когда вы пытались распечатать его), либо вы не находитесь в каталоге, который, как вы думаете, вы находитесь.

Пытаться

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

и внимательно проверьте имя файла. Вы также можете use Cwd; и распечатать текущий каталог.

person cjm    schedule 22.08.2009
comment
Спасибо cjm: Я видел это после того, как опубликовал свое решение, но вы были правы. - person blt04; 23.08.2009

Я нашел решение:

Столбец 27 - последний столбец, и файл закодирован с окончанием строки 0d0a (\ r \ n). chomp удалял только 0a (\ n). Не уверен, почему я не видел этого раньше, но это не имеет ничего общего с UTF16.

Добавление:

s/\r$//;

после того, как chomp устранит проблему.

Спасибо за вашу помощь - извините, что отправил вас по кроличьей тропе.

person blt04    schedule 22.08.2009
comment
Вы также можете попробовать :crlf:encoding(UTF-16), хотя я никогда не пробовал использовать: crlf с UTF-16, поэтому я не уверен, работает ли это. Я использовал только: crlf с однобайтовыми кодировками. - person cjm; 23.08.2009

Если, как вы говорите, в фактическом имени файла используются только символы 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. Ну что ж.

person Sinan Ünür    schedule 22.08.2009
comment
Вы могли бы подумать. Но это не так. -e по-прежнему возвращает false. Просто чтобы протестировать остальную часть моего кода, я попытался жестко закодировать имя файла внутри файла Perl, и это сработало. Чтение из файла iTunes UTF16 (даже с вашим предложением нулевой замены) не работает. - person blt04; 23.08.2009
comment
Попробуйте использовать utf8: downgrade ($ filename) перед заменой null. - person Inshallah; 23.08.2009
comment
Что ж, тогда давайте посмотрим на отладку, что на самом деле внутри $ filename, байт за байтом? - person bobince; 23.08.2009
comment
Еще раз спасибо, Синан. Я наконец увидел 0d0a, когда присмотрелся через xxd. - person blt04; 23.08.2009