【发布时间】:2021-12-30 08:37:24
【问题描述】:
我需要自动从电子邮件内容和标题中确定字符串的字符编码。在大多数情况下,这不是问题,但偶尔会有一封包含内容和/或标题具有奇怪字符(例如 en dash)的电子邮件。现在我收到了一个答案,如果我在特定电子邮件的特定标头上对其进行静态测试,从技术上讲似乎可行,但是这公然忽略了导入电子邮件需要是一个完全自动化的过程这一事实,在这种情况下,我完全无法自动确定字符串的字符编码。
我已经从基本知识开始,例如检测似乎可以保证会出现字符编码问题的常见问题字符。然而,strpos('en dash: –', '–') 在有意/手动测试时工作正常,但直接添加到自动化流程时会彻底失败。我猜测问题在于字符串参数具有 UTF-8 编码,而自动化过程正在测试一个还不是 UTF-8 的字符串,因此在内部相同的字符没有使用相同的子集代码(通过字符编码)。
所以我的第二次尝试是mb_detect_encoding 的第二个参数可以是一个数组。所以我尝试了以下方法:
$encodings = array('UTF-8','UCS-4','UCS-4BE','UCS-4LE','UCS-2','UCS-2BE','UCS-2LE','UTF-32','UTF-32BE','UTF-32LE','UTF-16','UTF-16BE','UTF-16LE','UTF-7','UTF7-IMAP','ASCII','EUC-JP','SJIS','eucJP-win','SJIS-win','ISO-2022-JP','ISO-2022-JP-MS','CP932','CP51932','SJIS-mac','SJIS-Mobile#DOCOMO','SJIS-Mobile#KDDI','SJIS-Mobile#SOFTBANK','UTF-8-Mobile#DOCOMO','UTF-8-Mobile#KDDI-A','UTF-8-Mobile#KDDI-B','UTF-8-Mobile#SOFTBANK','ISO-2022-JP-MOBILE#KDDI','JIS','JIS-ms','CP50220','CP50220raw','CP50221','CP50222','ISO-8859-1','ISO-8859-2','ISO-8859-3','ISO-8859-4','ISO-8859-5','ISO-8859-6','ISO-8859-7','ISO-8859-8','ISO-8859-9','ISO-8859-10','ISO-8859-13','ISO-8859-14','ISO-8859-15','ISO-8859-16','byte2be','byte2le','byte4be','byte4le','BASE64','HTML-ENTITIES','7bit','8bit','EUC-CN','CP936','GB18030','HZ','EUC-TW','CP950','BIG-5','EUC-KR','UHC','ISO-2022-KR','Windows-1251','Windows-1252','CP866','KOI8-R','KOI8-U','ArmSCII-8');
$encoding = mb_detect_encoding($s, $encodings, true);
$compare = mb_convert_encoding($s, 'UTF-8', $encoding);
foreach ($encodings as $k1)
{
if (mb_convert_encoding($s, 'UTF-8', $k1) === $s) {$encoding = $k1; break;}
}
不幸的是,基于我认为是相同的潜在问题,这似乎导致了同样的失败。
所以我的第三个想法是我正在寻找一些更有经验的验证。我可以将字符串转换为二进制形式(1 和 0,not 二进制数据)。然后我可以尝试转换字符串,然后将第二个字符串转换为二进制以比较两个二进制版本;如果他们=== 匹配,那么我可能已经确定了正确的字符编码?
现在我可以很容易地从一个不相关的线程中尝试这个with this answer,但是我不确定这是否是一个有效的想法。这都是为了回答我的问题:
如何确定字符串的实际字符编码,以便通过全自动验证将其转换为 UTF-8 而不会损坏数据?
通过验证,我说的是再次比较二进制数据之类的东西,但我不确定这是否是一种有效的方法。我知道我绝对讨厌破折号。
【问题讨论】:
标签: php validation utf-8 character-encoding