【问题标题】:Proper Charset to work with Vietnamese Characters (that isn't Unicode) in PHP在 PHP 中使用越南字符(不是 Unicode)的正确字符集
【发布时间】:2017-02-21 19:32:37
【问题描述】:

我已经搜索了一段时间,但还没有找到适合我的东西。我正在使用 PHP 表单使用 SAP DI API 将数据提交到 SAP。我需要弄清楚哪个字符集实际上可以让我存储和使用越南字符。

UTF8 似乎适用于很多字符,但 ô 变成了 ô。更重要的是,有字符限制,而 UTF-8 打破了字符限制。如果我有一个 30 个字符的字符串,它会告诉 API 它超过 50 个。存储在 MySQL 中也是如此——如果有 varchar 字符限制,UTF-8 会导致字符串超过它。

不幸的是,当我搜索时,UTF-8 似乎是人们对越南字符的唯一建议。如果我根本不对字符进行编码,它们就会被存储为它们的 html 字符代码。我也尝试过 ISO-8859-1,转换成 UCS-2 或 UCS-4 ......我真的很茫然。如果有人有处理越南字符的经验,我们将不胜感激。

更新

看来问题可能出在我在 Windows 上的 wampserver 上。这是一些让我感到困惑的代码:

$str = 'VậTCôNG';
$str1 = utf8_encode($str);
if (mb_detect_encoding($str,"UTF-8",true) == true) {
    print_r('yes');
    if ($str1 == $str) {
        print_r('yes2');
    }
}
echo $str . $str1;

这会在浏览器中打印“yes”而不是“yes2”,并且 $str.str1 = “VậTCôNGVáºTCôNG”。

我的 php.ini 文件包含:

default_charset = "utf-8"

和我的 httpd.conf 文件:

AddDefaultCharset UTF-8

我正在运行的 php 文件有:

header("Content-type: text/html; charset=utf-8");

所以我现在想知道:如果原始字符串是 utf-8,为什么它不等于本身的 utf8 编码?为什么 utf8 编码返回错误的字符? wampserver 配置有问题吗?

【问题讨论】:

  • UTF-8 是你最终要走的路,没有严肃的选择。并且 UTF-8 字符集肯定包含越南字符,它们被“更改”的事实必须是您的字符集的一些本地问题。但是,您必须了解 UTF-8 编码实际上是如何工作的,才能理解字符串长度的这些变化。
  • @arkascha 感谢您的回复。我对 UTF-8 的问题是,如果我对 SAP DI API 有 50 个字符的硬字符限制,并且字符串是 32 个带有几个越南字符的字符串,它将超过限制而无法输入。即使我确实修复了字符集问题,这似乎也是一个交易破坏者。
  • @arkascha 忘记这个回复。我想你是正确的。我更新了我的帖子,你知道为什么会这样吗?或者我的设备可能会出现什么本地问题?
  • 这里有几个问题:1. 您假设 X===utf8_encode(X),但这肯定不是正确的。你从哪里得到应该是正确的想法? 2.字符编码检测是一件棘手的事情。对于给定的字符串,它可能会提供正确的响应,也可能会失败。这实际上是在文档中特别提到的。简单示例:any 字符串可以正确解释为 8 位编码。这是否意味着它是?不!唯一可能的是明确检测出 some 字符串肯定是 not 有效的 utf8 编码字符串。 3.停止使用浏览器进行测试,使用CLI。
  • 实际上,众所周知,MS-Windows 存在 unicode 问题,抱歉。只有它无法隐藏其封闭和有限起源的领域之一。您可以使用hexeditor 自己测试您的原始字符串。那是(在我看来)真正允许窥视文件真正包含的内容的唯一工具。如果您了解 UTF 编码的实际工作原理,您可以在其中发现多字节序列。所有的 API、所有的浏览器都只在你和数据之间添加层,层试图变得聪明并“修复”实际上经常失败的东西......

标签: php mysql utf-8 character-encoding sap


【解决方案1】:

ôô 的“Mojibake”。也就是说,您确实拥有 UTF-8,但代码中的某些东西破坏了它。

查看Trouble with utf8 characters; what I see is not what I stored 并搜索 Mojibake。它说要检查这些:

  • 要存储的字节需要进行 UTF-8 编码。解决这个问题。
  • 插入和选择文本时的连接需要指定utf8或utf8mb4。解决这个问题。
  • 该列需要声明为CHARACTER SET utf8(或utf8mb4)。解决这个问题。
  • HTML 应以 <meta charset=UTF-8> 开头。

可以恢复数据库中的数据,但这取决于尚未提供的详细信息。

http://mysql.rjweb.org/doc.php/charcoll#fixes_for_various_cases

每个越南语字符占用 2-3 个字节 用于 UTF-8 编码。目前还不清楚“hard 50”是真的字符限制还是字节限制。

如果你碰巧有 Mojibake 的兄弟“双重编码”,那么越南语字符将占用 4-6 个字节,感觉就像 2-3 个字符。请参阅第一个链接中的“测试数据”。

如何在 MySQL 中“撤消”Mobibake 的示例: CONVERT(BINARY(CONVERT('VậTCôNG' USING latin1)) USING utf8mb4) --> 'VậTCôNG'

“双重编码”有点像 Mojibake 两次。即一方将其视为 latin1,另一方视为 UTF-8,但两次。

VậTCôNG,作为 UTF-8,是十六进制 56e1baad5443c3b44e47。如果该十六进制被视为字符集cp850keybcs2,则字符串为Vß║¡TC├┤NG

【讨论】:

  • 嗨@Rick James,我更新了我的帖子以传达我目前的情况。 mojibake 和双重编码一样吗?不幸的是,我没有在数据库中使用数据(现在只是直接在 PHP 中输​​入一个字符串),所以我不确定如何测试。如果 SAP DI API 将我的字符转换为 mojibake,这是否意味着它自己在进行编码?似乎 API 导入字符与在它们上运行 utf8_encode 具有相同的效果,即两者都返回 VáºTCôNG。你知道在这种情况下该怎么做吗?
  • 双重编码有点像 Mojibake 两次。我添加到我的答案中。抱歉,我不知道如何纯粹在 PHP 中处理它。我花了很长时间才弄清楚 MySQL 中的那个和其他 4 个错误案例。
【解决方案2】:

将其更改为 VISCII。

Input: ô 
Output: ô

您可以在Charset converter 进行测试。

【讨论】:

    猜你喜欢
    • 2019-03-08
    • 2019-08-15
    • 2018-12-04
    • 2011-04-18
    • 1970-01-01
    • 2019-12-18
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多