我想将一些来自UTF-8数据库的文本输出到CP1252(又名Latin1)中的文件。为此,我使用Text :: Iconv工作正常,除非要转换的字符串中的字符被分解。这是否是iconv库的失败是我提出的一个问题,答案并不明显。由于iconv在组合字符上工作正常,因此解决方案是首先规范化我的字符串,但我似乎无法做到这一点:
use strict;
use warnings;
use Data::Hexdumper qw(hexdump);
use Unicode::Normalize;
my $v = "É"; # E=U+0045 followed by combining ´=U+0301. UTF-8: 0x45CC81
print "'$v'\n";
print hexdump($v);
my $n = NFC $v; # should be É=U+00C9. UTF-8: 0xC389
print "'$n'\n";
print hexdump($n);
但这是我得到的输出:
'É'
0x0000 : 45 CC 81 00 00 00 00 00 00 00 00 00 00 00 00 00 : E...............
'É'
0x0000 : 45 CC 81 00 00 00 00 00 00 00 00 00 00 00 00 00 : E...............
换句话说,NFC(转换为标准化表格C)功能没有做任何事情。我错过了什么吗?我在Mac OS X 10.7.3上使用Perl 5.12.3。
这只是我在Perl中处理文本问题的开始,我不会想到这一点。谢谢你的帮助。
编辑:某些上下文似乎很有用。当然,use utf8
条款可以帮助我做出很多有用的例子。我的实际问题当然不是字符串文字。
首先,我从答案中了解到,我需要了解很多关于Perl的知识。事实上,我不是Perl程序员,而是Objective-C / Cocoa程序员,而这些问题根本没有出现。
所以我开始读出来,我发现Perl文档很混乱,例如当它谈到本机编码与UTF-8不同时。它没有说的是如何在Mac OS X平台上翻译它,其中UTF-8 是本机编码。
在任何情况下,上下文是我的程序在texte文件中生成输出,可以有多种格式(包括csv和Unimarc),以及几种编码(最常见的四种是UTF-8,CP1252,MARC8和ISO-5426)。用户的选择。
它从一些数据库(目前是mySQL或SQL Server)获取输入,其中数据通常以UTF-8编码(但有时在CP1252中)。
答案 0 :(得分:3)
你缺少的是$v
被设置为'E'字符和组合急性重音变音符号的 utf-8编码,而不是组合急性变音符号本身。要解决这个问题,你需要做类似
1)use utf8
- 使Perl自动utf-8解码您的源代码
2)明确解码$v
my $v = chr(0x45) . chr(0xCC) . chr(0x81);
use Encode;
$v = Encode::decode('utf-8', $v); # now $v is 0x45 0x301
3)使用chr
将$v
明确设置为您的意思
my $v = chr(0x45) . chr(0x301);
我不会真的推荐数字(2),但是当你没有use utf8
时,我将其作为一种方式来说明你的脚本会发生什么。
答案 1 :(得分:2)
É
尝试了以下内容:
perl -C3 -lwe '$_ = qq(\x45\x{0301}); print'
在Cygwin上适用于5.10.1。
我可能会遗漏一些东西......但是看起来你在这里采用的是一种非常低级的文本处理方法。
首先,您说您从数据库中获取数据,其中编码为UTF-8。没关系。因此,如果驱动程序没有自动检测编码,请考虑告诉它。你不是说你正在使用哪个数据库,但是你可能会通过点击DBI manual以及你用于“utf”或“编码”的驱动程序(DBD::*
)找到一些东西。 ”
然后,给定数据库连接的适当编码设置,您的文本应该以Perl形式到达,例如,文本。只是文字,没有编码。例如,在Java中。是的,字符串有一些内部编码,但你不应该打扰它是什么。
然后,在写入文件时,只需使用以下代码:
open my $fh, '>:encoding(CP1252)', $filename or die "open $filename: $!";
print $fh $text_from_db;
close $fh;
这应该就是你需要做的一切。
您使用Text::Iconv
的任何特殊原因?我认为你应该使用Encode
module。但是对于你问题中概述的工作,你甚至不需要那个。
你正在使用Perl 5.12.3,因此Unicode处理应该适用于所有奇怪的边界情况。这些问题主要是可以追溯到几年前的perls。我认为5.12和5.10系列应该没问题。没有方便的细节,但我曾经不得不使用旧的5.6.1进行Unicode工作,其中Unicode支持是实验性的,而且非常糟糕。
答案 2 :(得分:2)
你没告诉Perl你的文件是UTF-8。
您没有告诉Perl如何对输出进行编码。
use strict;
use warnings;
use utf8; # UTF-8 source.
use open ':std', ':encoding(UTF-8)'; # UTF-8 output. Don't forget to chcp 65001..
use Data::Dumper qw( Dumper );
use Unicode::Normalize qw( NFC );
local $Data::Dumper::Useqq = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Indent = 0;
my $v = "\x{0045}\x{0301}";
print "'$v'\n";
print Dumper($v), "\n";
my $n = NFC $v;
print "'$n'\n";
print Dumper($n), "\n";
(我在加载Hexdumper时遇到问题。)