Может ли Perl-скрипт с кодировкой utf8 открыть имя файла, закодированное как GB2312?

Я не говорю о чтении содержимого файла в кодировке utf-8 или не-utf-8 и прочем. Речь идет об именах файлов. Обычно я сохраняю свой Perl-скрипт в системной кодировке по умолчанию, в моем случае "GB2312", и у меня не будет проблем с открытием файлов. Но для целей обработки у меня теперь есть некоторые файлы сценариев Perl, сохраненные в кодировке utf-8. Проблема в том, что эти скрипты не могут открывать файлы, имена которых состоят из символов, закодированных в кодировке "GB2312", и мне не нравится идея переименовывать мои файлы.

Может у кого есть опыт борьбы с такой ситуацией? Спасибо, как всегда, за любое руководство.

Изменить

Вот минимизированный код, демонстрирующий мою проблему:

# I'm running ActivePerl 5.10.1 on Windows XP (Simplified Chinese version)
# The file system is NTFS

#!perl -w
use autodie;

my $file = "./测试.txt"; #the file name consists of two Chinese characters
open my $in,'<',"$file";

while (<$in>){
print;
}

Этот тестовый сценарий может работать хорошо, если он сохранен в кодировке «ANSI» (я предполагаю, что кодировка ANSI такая же, как GB2312, которая используется для отображения китайских иероглифов). Но это не сработает, если будет сохранено как «UTF-8», а сообщение об ошибке будет следующим:

Can't open './娴嬭瘯.txt' for reading: 'No such file or directory'.

В этом предупреждающем сообщении «娴嬭瘯» — бессмысленные ненужные символы.

Обновить

Сначала я попытался закодировать имя файла как GB2312, но это не работает :( Вот что я пробовал:

#!perl -w
use autodie;
use Encode;

my $file = "./测试.txt";
encode("gb2312", decode("utf-8", $file));
open my $in,'<',"$file";

while (<$in>){
print;
}

В настоящее время я думаю так: имя файла в моей ОС — 测试.txt, но оно закодировано как GB2312. В скрипте Perl имя файла выглядит так же для человеческого глаза, по-прежнему 测试.txt. Но для Perl они отличаются, потому что имеют разные внутренние представления. Но я не понимаю, почему проблема сохраняется, когда я уже преобразовал имя файла в Perl в GB2312, как показано в приведенном выше коде.

Обновить

Сделал, наконец-то сделал :)

Предложение @brian правильное. Я сделал ошибку в приведенном выше коде. Я не вернул закодированное имя файла $file.

Вот решение:

#!perl -w
use autodie;
use Encode;

my $file = "./测试.txt";
$file = encode("gb2312", decode("utf-8", $file));
open my $in,'<',"$file";

while (<$in>){
print;
}

person Mike    schedule 16.11.2009    source источник
comment
Какую ОС и файловую систему вы используете?   -  person JB.    schedule 16.11.2009
comment
Можете выложить код для открытия файлов? Это может быть очень полезно для понимания проблемы.   -  person Jack M.    schedule 16.11.2009
comment
@JB, я использую Windows XP (версия на упрощенном китайском языке), а файловая система - NTFS.   -  person Mike    schedule 17.11.2009
comment
@ Джек М. Хорошо, я обновляю свой вопрос.   -  person Mike    schedule 17.11.2009
comment
Я думаю, вы должны use utf8; в самом верху, а затем пропустить шаг decode. Прагма utf8 сообщает Perl, что ваш исходный код (включая строковые литералы) уже имеет кодировку UTF-8.   -  person cjm    schedule 26.11.2009
comment
@cjm, когда мы используем utf-8, Perl видит китайские символы в исходном коде как шестнадцатеричные числовые представления в кодировке utf-8, но моя система Windows обрабатывает эти числовые представления как кодировку GB2312 и декодирует их соответствующим образом, что неправильно. Пропуск шага декодирования не решит проблему.   -  person Mike    schedule 26.11.2009


Ответы (1)


если ты

 use utf8;

в вашем Perl-скрипте это просто сообщает Perl, что источник находится в UTF-8. Это не влияет на то, как Perl взаимодействует с внешним миром. Включаете ли вы какие-либо другие функции Perl Unicode?

У вас проблемы с каждым именем файла или только с некоторыми из них? Можете ли вы привести несколько примеров или небольшой демонстрационный сценарий? У меня нет файловой системы, которая кодирует имена как GB2312, но пробовали ли вы кодировать имена файлов как GB2312, прежде чем вызывать open?

Если вы хотите, чтобы определенные строки были закодированы с помощью определенной кодировки, вы можете использовать модуль Encode. Попробуйте это с вашими именами файлов, которые вы даете open.

person brian d foy    schedule 16.11.2009
comment
@Брайан, спасибо за ответ. Могу ли я позволить Perl сначала преобразовать имя файла в кодировке GB2312 в UTF-8, чтобы он мог распознавать имя файла? Я знаю, как кодировать содержимое файла, не закодированное в utf-8, как utf-8, но не подумал сделать это с именем файла. - person Mike; 17.11.2009
comment
@Брайан, спасибо! Я наконец решил проблему. Вы совершенно правы! Решение именно такое, как вы и предполагали: закодируйте имена файлов как GB2312 перед вызовом open. - person Mike; 17.11.2009