我需要编码还是解码?

时间:2015-10-21 12:20:20

标签: html mysql perl encode utf8-decode

我有一个非常奇怪的情况。 在我们的应用程序中,它构建在perl和mysql中。我们有latin1 charset的遗留表。其中一个用户已将阿拉伯数据输入此表。 当我运行查询以从此表中获取详细信息时,它看起来像这样。

أخٓاÙ,ياتأأعÙ...آأÙ...ÙضÙع

在应用程序中,我们有一个显示它的页面,它正确显示阿拉伯字符。

أخلاقياتالأعمالالموضوع

我们有一个ETL(提取,转换和加载)过程,它将此数据转储到另一个Star架构的数据库。这里的数据保存在UTF-8字符集的表中。

现在,当我查询此表时,同样的字段显示为

Ã〜Â~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ €| ~~~~~~~~~~

在UI中,我们有另一个页面显示新表中的数据。这里阿拉伯字符没有正确显示。这就是它在前端的显示方式。

أخٓاÙ,ياتأأعÙ...آأÙ...ÙضÙع

上面的文字与我在MYSQL DB latin1表中看到的初始输入相似或相同。

如何在页面中正确显示阿拉伯字符。 请帮忙。

2 个答案:

答案 0 :(得分:3)

通常,规则是您应解码来自外部源的文本,并将编码文本发送到外部接收器。在您的情况下,您从数据库中获取看起来像UTF-8编码的数据,因此您应该解码它。但看起来它已被部分解码。看一下这个程序

use utf8;
use strict;
use warnings;
use feature 'say';

my $xx = 'أخلاقيات الأعمال الموضوع';
my $yy = 'أخلاقيات الأعمال الموضوع';
utf8::encode($yy);

say length $xx;
say join ' ', map { sprintf '%04X', ord } split //, $xx;

say length $yy;
say join ' ', map { sprintf '%04X', ord } split //, $yy;

输出

46
00D8 00A3 00D8 00AE 00D9 201E 00D8 00A7 00D9 201A 00D9 0160 00D8 00A7 00D8 00AA 0020 00D8 00A7 00D9 201E 00D8 00A3 00D8 00B9 00D9 2026 00D8 00A7 00D9 201E 0020 00D8 00A7 00D9 201E 00D9 2026 00D9 02C6 00D8 00B6 00D9 02C6 00D8 00B9
46
00D8 00A3 00D8 00AE 00D9 0084 00D8 00A7 00D9 0082 00D9 008A 00D8 00A7 00D8 00AA 0020 00D8 00A7 00D9 0084 00D8 00A3 00D8 00B9 00D9 0085 00D8 00A7 00D9 0084 0020 00D8 00A7 00D9 0084 00D9 0085 00D9 0088 00D8 00B6 00D9 0088 00D8 00B9

这显示了您直接从数据库中获取的字符串中每个字符的Unicode代码点,以及它应表示以UTF-8字节编码的阿拉伯语文本。正如您所看到的,除了0x82和0x8A之间的偶然值之外,一切都很好地匹配,这些值在数据库文本中被广泛的其他宽泛的Unicode字符替换为

0082 => 201A,
0084 => 201E,
0085 => 2026,
0088 => 02C6,
008A => 0160,

很明显,你从数据库中检索的内容应该是UTF-8编码的文本,所以它应该只是字节值,所以我很难理解那些宽字符在那里做什么

所以简短的回答是你应该use Encodedecode_utf8从数据库中获取的字符串。但是那些广泛的角色会破坏这种方法,所以你需要找出你获得它们的原因

我建议您使用我的程序中以十六进制值转储字符串的行,并在从数据库中提取字符串后直接应用它。

say join ' ', map { sprintf '%04X', ord } split //, $value;

这样我们就能看到第一手的情况。因为在您的程序之间,通过Stack Overflow服务器到我的桌面之间会有很多编码/解码,而且这些阶段中的任何一个都可能是罪魁祸首

答案 1 :(得分:0)

我不确定阿拉伯语是否受此影响,但MySql的utf8编码并不总是人们想要的。阅读this后,我总是使用utf8mb4编码。

如果没有其他工作可能值得在本地副本上尝试。