Нормализация Unicode - имена файлов в текстовых файлах против имен файлов в файловой системе

Просто начинаю работать над одним приложением perl. Нужен совет, как (правильно) разобраться с unicode filenames против filenames in the file content портативный способ.

Вот несколько систем, в мире Windows и Unix используется различная кодировка Unicode (Unixes utf8, Windows - не знаю), но Linux и Mac OS X отличаются нормализацией Unicode для имен файлов. (OS X - принудительный NFD, Linux - "обычно" NFC).

Все советы, которые я уже прочитал, гласят: (всегда нормализуйте данные Юникода на границах приложения) - но вопрос в том, что является правильным - наиболее переносимым способом сделать это?

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

Итак, вопросы, что является правильным методом создания портативных приложений и работы с именами файлов в:

  • opendir / READDIR
  • glob и подобные "файловые операции"
  • текстовые файлы (что будет содержать имена файлов)
  • внутренние компоненты Perl...
  • Другой?

Когда и где проводится нормализация? Как сохранить текстовые файлы utf8, что в их содержании содержатся имена файлов?

Я знаю, здесь много вопросов, связанных с perl-unicode, уже в StacOverflow. Я копал, вероятно, большинство из них - но до сих пор не понимаю, что такое "рекомендуемая" практика для решения приведенного выше списка вопросов.

Нужно ли будет делать модули для работы с конкретными отличиями операционной системы? Или здесь уже есть модули CPAN, которые имеют дело с различиями ОС в файловых операциях?)

Может кто-нибудь указать мне хороший ресурс с рекомендованными методами? Или это намного проще, чем я думаю сейчас?

2 ответа

Решение

Примечание. Запросы на сторонние ресурсы не рекомендуется использовать в Stackru. Кроме того, вопрос о том, как нормализовать текст Unicode в целом, слишком широк.

Относительно имен файлов, возвращаемых из readdir или же glob Хорошая практика - декодировать и нормализовать их. Рассмотрим следующий код:

#!/usr/bin/perl
use strict;
use utf8;

use File::Slurp;
use Unicode::Normalize;

binmode(STDOUT, ':utf8');

write_file("Unicode Test - Übersee.txt", "text");

opendir(my $dh, ".") or die($!);
while (my $entry = readdir($dh)) {
    utf8::decode($entry);

    if ($entry =~ /^Unicode Test - (.*)\.txt/) {
        my $word = $1;
        print("got $word\n");
        print("matches 'Übersee': ", $word eq "Übersee" ? "yes" : "no", "\n");
        my $nfc = NFC($word);
        print("NFC matches 'Übersee': ", $nfc eq "Übersee" ? "yes" : "no", "\n");
    }
}   
closedir($dh);

На OS X это будет выводить:

got Übersee
matches 'Übersee': no
NFC matches 'Übersee': yes

Это связано с изменением NFD, которое HFS использует для нормализации имен файлов.

По сути, нормализуйте все входные данные из источников, где вы не можете быть уверены, что они в нормальной форме. В большинстве случаев вам следует использовать NFC, потому что большинство данных уже будет в NFC.

Насколько я могу судить, MS не проводит нормализацию в своей файловой системе. Это означает, что если вы планируете этот сценарий наихудшего случая, вы будете хороши на других ОС.

Техника, которая, кажется, работает, это запросить у ОС файлы, которые она видит. Создайте нормализованный хеш-код на основе нормализованной формы по вашему выбору и содержащий в качестве значений имена из ОС. Это не элегантно, но работает.

Другие вопросы по тегам