我曾经处于完全相同的位置。生产MySQL服务器被设置为latin1,旧数据也是latin1,新数据是utf8但存储在latin1列中,然后添加了utf8列...每行可以包含任意数量的编码。
最大的问题是没有单一的解决方案可以纠正所有问题,因为许多传统编码使用相同的字节表示不同的字符。这意味着您将不得不采用启发式方法。在我的Utf8Voodoo
类中,有一个巨大的数组,其中包含从127到255的字节,即传统的单字节编码非ASCII字符。
public static $legacyEncodingsMagicBytes = array(
'/[\x81\x8D\x8F\x90\x9D]/' => array('CP850'),
'/[\x80\x82-\x8C\x8E\x91-\x9C\x9E\x9F]/' => array('Windows-1252', 'CP850'),
'/./' => array('ISO-8859-15', 'ISO-8859-1', 'Windows-1252', 'CP850'),
);
public static $legacyEncodingsLikelyBytes = array(
'/\x80/' => array(
'Windows-1252' => +10,
),
'/[\x93-\x97\x99]/' => array(
'Windows-1252' => +1,
),
'/[\x86\x87\x89\x8A\x8C\x8E\x9A\x9C\x9E]/' => array(
'Windows-1252' => -1,
),
'/\xA4/' => array(
'ISO-8859-15' => +10,
),
'/[\xA6\xBD]/' => array(
'ISO-8859-15' => -1,
),
'/[\x82\xA7\xCF\xFD]/' => array(
'CP850' => +1
),
'/[\x91\x92\xB0-\xB3\xB9-\xBC\xC1-\xC5\xC8-\xCE\xD9-\xDC\xDF\xE7\xE8]/' => array(
'CP850' => -1
),
然后,您需要在字符串中循环遍历字节(而不是字符),并保留分数。如果您需要更多信息,请告诉我。