Unicode规范化 - 文本文件中的文件名与文件系统上的文件名

时间:2013-11-20 18:01:58

标签: perl utf-8 filenames normalization unicode-normalization

刚开始处理一个perl应用程序。需要一些建议如何(正确)处理unicode filenames vs filenames in the file content - 便携式方式。

以下是几个系统,Windows和Unix世界使用不同的unicode编码(Unixes utf8,Windows - 不知道),但Linux和Mac OS X对文件名的unicode规范化不同。 (OS X - 强制执行NFD,Linux - “通常是”NFC)。

我已经读到的所有建议都说:(始终在应用程序的边界上规范化unicode数据) - 但问题是 - 什么是正确的 - 最便携的方式呢?

问题在于,OS X(创建文本文件时)使用NFC作为内容。我不知道其他系统在使用什么。

所以问题是,制作便携式应用程序和处理文件名的正确方法是什么:

  • 执行opendir / READDIR
  • glob和类似的“文件操作”
  • textfiles(将包含文件名)
  • perl internals ...
  • 其他?

归一化的时间和地点?如何保存utf8文本文件,其内容中包含文件名?

我知道,这里有许多与StacOverflow相关的perl-unicode相关问题。我挖掘了他们中的大多数 - 但仍然不明白什么是“推荐”的做法来处理上面的问题列表。

是否需要制作模块来处理特定的操作系统差异?或者这里是alredy CPAN模块,它们处理文件操作中的操作系统差异?)

有人可以通过推荐的做法向我指出一些好的资源吗?或者我现在想的更简单了?

2 个答案:

答案 0 :(得分:2)

据我所知,MS对其文件系统不执行规范化。这意味着如果你计划这种最坏的情况,你就会对其他操作系统有所帮助。

似乎有效的技术是查询操作系统查看的文件。创建一个标准化哈希,键入您选择的规范化形式&包含来自OS的名称作为值。它不优雅,但它的工作原理。

答案 1 :(得分:2)

注意:不鼓励在StackOverflow上请求异地资源。此外,如何规范化Unicode文本的问题过于宽泛。

关于从readdirglob返回的文件名,最好对其进行解码和规范化。请考虑以下代码:

#!/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

这是由于HFS用于规范化文件名的NFD的变化。

从本质上讲,将来自您无法确定其处于正常形式的来源的所有输入标准化。在大多数情况下,您应该使用NFC,因为大多数数据已经在NFC中。