4

刚开始研究一个 perl 应用程序。需要一些建议如何(正确)处理unicode filenamesvs 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 获取内容。我不知道其他系统使用什么。

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

  • 开放目录/读取目录
  • glob 和类似的“文件操作”
  • 文本文件(将包含文件名的内容)
  • perl 内部...
  • 其他?

何时何地进行标准化?如何保存内容中包含文件名的 utf8 文本文件?

我知道,StacOverflow 中已经有许多与 perl-unicode 相关的问题。我可能挖掘了其中的大部分——但仍然不明白处理上述问题列表的“推荐”做法是什么。

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

有人可以通过推荐的做法向我指出一些好的资源吗?还是像我现在想的那样简单得多?

4

2 回答 2

2

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

关于从readdiror返回的文件名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

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

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

于 2013-11-20T23:07:45.650 回答
2

据我所知,MS 没有对其文件系统进行规范化。这意味着,如果您为这种最坏的情况做好计划,您将在其他操作系统上表现出色。

一种似乎有效的技术是向操作系统查询它看到的文件。创建以您选择的规范化形式为键的规范化哈希,并包含来自操作系统的名称作为值。它并不优雅,但它确实有效。

于 2013-11-20T20:00:06.053 回答