【问题标题】:Revert badly encoded umlauts恢复编码错误的变音符号
【发布时间】:2015-11-01 20:57:57
【问题描述】:

由于某种原因,我的特殊字符在 mysql 数据库中被编码为以下字符串:

Ã?

显示为:

Ã?

但实际上应该显示为:

Ö
  1. 这里出了什么问题?我到处使用 UTF-8。

  2. 如何在不重新创建所有内容的情况下解决此问题?

【问题讨论】:

  • 角色是如何进入这些实体的?该字符表示对于实体是正确的。
  • Ã?真的应该显示为Ã?。我认为问题在于插入的内容
  • @Bart Scheffer 我想你的意思是html_entity_decode
  • 我的猜测是 Ö 甚至在将值插入数据库之前就出现了问题。 Ö 的 utf-8 序列的第一个字节在 ANSI 中是 Ã,然后如果在错误地将其解释为 ANSI 之后,这将被转义为 HTML,您将得到您所阅读的内容。似乎不是数据库自己进行的操作类型。正是在输入过程中出了问题。你能显示插入的代码吗?
  • 也许你应该用过$event = html_entity_decode(strip_tags($_POST["event"]));

标签: php mysql encoding diacritics


【解决方案1】:

我在PHP中执行了以下操作:

<?php
echo str_replace("&", "&amp;", htmlentities("Ö", 0, "ISO-8859-1")) , '<br />';    
echo str_replace("&", "&amp;", htmlentities("Ö", 0, "UTF-8")), "</br>";
?>

str_replace 只是用来显示任何 HTML 助记符,否则 被浏览器翻译成原始字符,这是我不希望发生的。

你会得到这个作为输出:

&Atilde;�
&Ouml;

您将识别出第一个值是您在数据库中找到的值,而第二个值 有点像你想要的。 除此之外,htmlentities 的第三个参数的默认值 depends on your PHP versionISO-9959-1 在版本 5.3 的情况下,您使用的那个。 还要意识到没有指定字符编码的HTML 文档将 默认情况下以ISO-8859-1 格式发布表单数据。 结合所有这些可能会提供有关问题原因的线索:

我的猜测是数据以UTF-8 正确发布到服务器,但随后htmlentities 将其解释为非UTF-8,单字节编码,因此将一个多字节字符转换为两个单字节字符。

现在要采取措施避免这种情况继续发生:

首先确保您的HTML 表单具有UTF-8 编码,因为这决定了 表单将用于将其数据发送到服务器的默认编码:

<head>
    <meta charset="UTF-8">
</head> 

确保这不会被表单标签的accept-charset 中的另一种编码所推翻 属性。

然后,跳过htmlentities 电话。你不应该把角色变成他们的 HTML mnemonic 将它们存储在数据库中时。 mysql 支持UTF-8 字符,所以就这样存储它们。

对于第二个问题,您必须找到所有案例并在找到时批量替换它们 新实例。通过生成一些 SQL 语句,您可以获得一些帮助 使用PHP 脚本,如下所示:

<?php
    // list all your non-ASCII characters here. Do not use str_split.
    $chars = ["Ö","õ","Ũ","ũ"];
    foreach ($chars as $ch) {
        $bad = str_replace("&", "&amp;", htmlentities($ch, 0, "ISO-8859-1"));
        echo "update mytable set myfield = replace(myfield, '$bad', '$ch') 
                where instr(myfield, '$bad') > 0;<br />";
    }
?>

此脚本的输出将如下所示:

update mytable set myfield = replace(myfield, '&Atilde;�', 'Ö') where instr(myfield, '&Atilde;�') > 0;
update mytable set myfield = replace(myfield, '&Atilde;&micro;', 'õ') where instr(myfield, '&Atilde;&micro;') > 0;
update mytable set myfield = replace(myfield, '&Aring;&uml;', 'Ũ') where instr(myfield, '&Aring;&uml;') > 0;
update mytable set myfield = replace(myfield, '&Aring;&copy;', 'ũ') where instr(myfield, '&Aring;&copy;') > 0;

当然,您可以决定创建一个 PHP 脚本,它甚至可以自己进行更新。

希望您可以使用此信息来解决问题。

【讨论】:

  • 感谢您的详细解答!第一部分是正确的!它是由开发服务器和实时服务器上的不同 php 版本引起的。关于第二部分,我可能需要明天再来找你,因为今天我现在无法测试这个脚本。
【解决方案2】:

对于 PDO,使用类似

$db = new PDO('dblib:host=host;dbname=db;charset=UTF-8', $user, $pwd);

&amp;Atilde;? 是两三件事出了问题,而不仅仅是一件! C396Ö 的 utf8 十六进制或两个字符 Ö 的 latin1 十六进制。要获得? 或黑色钻石,还需要其他一些问题。

让我们看看表中有什么;做

SELECT col, HEX(col) FROM tbl WHERE ...

(如果您已经完成了之前建议的replace(),那么桌子可能会更糟。或者它可能会被修复。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 2012-01-08
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多