数据库文本中出现奇怪字符:Ã、Ã、¢、â‚ €。

37

我不确定这是什么时候开始的。

我有一个新的代销联盟网站,从批发商那里收到产品目录的导出副本。 我将其格式化并导入Prestashop 1.4.4中。

网站前端包含产品文本内的奇怪字符组合:Ã,Ã,¢,â‚等。 它们出现在常见字符(如,-:等)的位置。

这些字符存在于大约40%的数据库表中,而不仅仅是像ps_product_lang这样的特定于产品的表。

另一个网站线程当数据库连接字符串使用不正确的字符编码类型时,会出现同样的问题

在/config/setting.inc中,没有提到字符编码字符串,只有MySQL引擎,它设置为InnoDB,与我在PHPMyAdmin中看到的匹配。

我导出了ps_product_lang,用正确的字符替换了所有这些字符的实例,以UTF-8格式保存了CSV文件,并使用PHPMyAdmin重新导入它们,指定UTF-8为语言。

然而,在PHPMyAdmin中进行新搜索之后,我在ps_product_lang中拥有了大约10倍于起始值的这些坏字符的实例。

如果问题就像指定正确的语言属性一样简单,请问我在哪里/如何设置数据库连接字符串,应该设置为什么?

顺便说一下,我尝试在此线程中提到的在PHPMyAdmin中运行此命令,但问题仍然存在:

SET NAMES utf8

更新: PHPMyAdmin显示:

MySQL字符集: UTF-8 Unicode (utf8)

这是我在上一次导入文件中使用的相同字符集,但却导致了更多字符损坏。在导入过程中,UTF-8被指定为导入文件的字符集。

更新2

这里有一个样本:

人们真正地过着无拘无束的生活,购买和租借电影、下载软件,在网上共享和存储文件。

更新3

我在PHPMyAdmin中运行了一个SQL命令来显示字符集:

  • character_set_client utf8
  • character_set_connection utf8
  • character_set_database latin1
  • character_set_filesystem binary
  • character_set_results utf8
  • character_set_server latin1
  • character_set_system utf8

因此,也许需要将我的数据库转换为UTF-8(或删除并重新创建)。如果MySQL服务器是latin1,这会带来问题吗?MySQL能够处理提供UTF-8内容但将其存储为latin1的翻译吗?我认为它不能,因为UTF-8是latin1的超集。我的Web托管支持在48小时内没有回复。或许对他们来说这太难了。


@AurelioDeRosa 上面添加了示例。 - Steve
我不太了解prestashop,但似乎它的字符编码不太好。无论如何,我看到其他人也有同样的问题:http://www.prestashop.com/forums/topic/34545-problem-with-encoding-characters/ - Aurelio De Rosa
这不仅仅是前端问题吗?phpMyAdmin设置为以错误的编码显示内容,客户端也没有设置使用UTF-8?需要在元标记中设置。 - MarianP
@MarianP 数据库和服务器是latin1,而PHPMyAdmin和CSV是UTF8。(请参见上面的更新3) - Steve
你不需要重置整个数据库来进行尝试。只需从CSV文件中获取一行“脏”数据,将其从utf-8转换为latin1,并将该行插入到数据库中。如果新行正确,则问题已解决。 - Aurelio De Rosa
如果有人遇到WordPress网站问题,请从wp-config.php文件中删除以下行:define('DB_CHARSET', 'utf8'); define('DB_COLLATE', 'utf8_unicode_ci'); - Suraj Rathod
6个回答

23

正如您在这里(http://en.wikipedia.org/wiki/UTF-8)所看到的,**真正的**名称是UTF-8。但是,在语句中可以没有破折号。 - Aurelio De Rosa
我知道,别担心。这只是为了澄清。事实上,正如你所看到的,我断言“语句中可以没有破折号”。此致敬礼。 - Aurelio De Rosa
@AlexV:我需要在PrestaShop中使用它吗?如果是的话,你知道怎么做吗? - Steve
@Steve 这应该是默认内置的。我查看了PrestaShop代码库,他们没有使用mysql_set_charset。所以我猜他们要么使用默认表字符集,要么在数据上动态转换。我的猜测是表格内容与表格字符集不匹配。 - AlexV
我可以从这些字符中看出这是正确的答案。这些字符是2字节序列的开头,数据库将其存储为单个字符,因为它期望的是Latin1。 - pguardiario
在Python中,使用codecs将其转换为UTF-8对我很有帮助。 - Code True

6
这肯定是一个编码问题。你的数据库和网站使用不同的编码方式,这就是问题的原因。如果你运行了该命令,你需要更改已经存在于表中的记录,将这些字符转换为UTF-8。更新:根据您的最后一条评论,问题的核心是您的数据库和数据源(CSV文件)使用不同的编码方式。因此,您可以将数据库转换为UTF-8,或者至少在获取CSV中的数据时,您需要将它们从UTF-8转换为latin1。您可以按照以下文章进行转换:将latin1转换为UTF8http://wordpress.org/support/topic/convert-latin1-to-utf-8

好的。现在看一下以下内容:http://www.bluebox.net/news/2009/07/mysql_encoding - Steve

5

这似乎是一个UTF-8编码问题,可能是由于数据库文件内容的双重UTF8编码引起的。

这种情况可能是由于选择或未选择字符集(例如在创建数据库备份文件时)以及保存数据库文件的文件格式和编码引起的。

我曾经在以下场景中看到过这些奇怪的UTF-8字符(由于我不再能访问相关数据库,因此描述可能不完全准确):

  • 据我回忆,数据库和表具有“uft8_general_ci”排序规则。
  • 备份数据库。
  • 在Windows上打开备份文件,使用UNIX文件格式和ANSI编码。
  • 通过将数据库备份文件的内容复制粘贴到phpMyAdmin中来还原数据库。

查看文件内容:

打开SQL备份文件并在文本编辑器中查看,会发现SQL备份文件中有奇怪的字符,如“sÃ¥”。值得一提的是,如果在另一个编辑器中打开同一文件,则可能会得到不同的结果。我在这里使用TextPad,但在SublimeText中打开相同的文件时,它会显示“sà ¥”,因为SublimeText正确地对文件进行了UTF8编码——尽管这在您开始尝试在PHP中修复问题时可能会有点令人困惑,因为您首先在SublimeText中看不到正确的数据。无论如何,这可以通过注意文本编辑器在呈现文件内容时使用的编码来解决。
这些奇怪的字符是双重编码的UTF-8字符,在我的情况下,第一个“Ô部分等于“Ô和“Â¥”=“¥”(这是我的第一个“编码”)。 "Ã¥"字符等于“å”的UTF-8字符(这是我的第二个编码)。
所以,“问题在于将“false”(UTF8编码两次)的utf-8转换回“正确”的utf-8(只有UTF8编码一次)”。
尝试在PHP中修复这个问题,结果有点具有挑战性: utf8_decode()无法处理这些字符。
// Fails silently (as in - nothing is output)
$str = "så";

$str = utf8_decode($str);
printf("\n%s", $str);

$str = utf8_decode($str);
printf("\n%s", $str);

iconv()函数出现“注意:iconv():在输入字符串中检测到非法字符”错误。

echo iconv("UTF-8", "ISO-8859-1", "så");

在这种情况下,另一个好的可能解决方案也会默默失败。

$str = "så";
echo html_entity_decode(htmlentities($str, ENT_QUOTES, 'UTF-8'), ENT_QUOTES , 'ISO-8859-15');

mb_convert_encoding() 静默处理:#

$str = "så";
echo mb_convert_encoding($str, 'ISO-8859-15', 'UTF-8');
// (No output)

尝试通过将MySQL数据库的字符集和排序规则转换为UTF-8来修复MySQL中的编码问题失败了。
ALTER DATABASE myDatabase CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE myTable CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

我看到有几种方法可以解决这个问题。

第一种是使用正确的编码进行备份(编码需要与实际数据库和表格编码匹配)。您可以通过在文本编辑器中打开生成的SQL文件来验证编码。

另一种方法是用单个UTF8编码字符替换双重UTF8编码字符。这可以在文本编辑器中手动完成。为了协助此过程,您可以从 UTF-8编码调试图表手动选择不正确的字符(可能只需替换5-10个错误)。

最后,脚本可以协助完成此过程:

    $str = "så";
    // The two arrays can also be generated by double-encoding values in the first array and single-encoding values in the second array.
    $str = str_replace(["Ã","Â¥"], ["Ã","¥"], $str); 
    $str = utf8_decode($str);
    echo $str;
    // Output: "så" (correct)

4
我今天遇到了一个类似的问题: mysqldump把我的utf-8编码的utf-8变音符号字符转换成了两个latin1字符,尽管文件本身是正常的utf8格式。
例如:"é"被编码为两个字符"é"。这两个字符对应于字母的utf8两个字节编码,但应该被解释为单个字符。
为了解决这个问题并在另一个服务器上正确导入数据库,我使用了ftfy(代表“Fixes Text For You”)(https://github.com/LuminosoInsight/python-ftfy)python库转换文件。该库正好符合我的期望:将错误编码的utf-8转换为正确编码的utf-8。
例如:这个latin1组合"é"变成了"é"。
ftfy带有一个命令行脚本,但它会转换文件,因此无法重新导入mysql。
我写了一个python3脚本来解决这个问题:
#!/usr/bin/python3
# coding: utf-8

import ftfy

# Set input_file
input_file = open('mysql.utf8.bad.dump', 'r', encoding="utf-8")
# Set output file
output_file = open ('mysql.utf8.good.dump', 'w')

# Create fixed output stream
stream = ftfy.fix_file(
    input_file,
    encoding=None,
    fix_entities='auto', 
    remove_terminal_escapes=False, 
    fix_encoding=True, 
    fix_latin_ligatures=False, 
    fix_character_width=False, 
    uncurl_quotes=False, 
    fix_line_breaks=False, 
    fix_surrogates=False, 
    remove_control_chars=False, 
    remove_bom=False, 
    normalization='NFC'
)

# Save stream to output file
stream_iterator = iter(stream)
while stream_iterator:
    try:
        line = next(stream_iterator)
        output_file.write(line)
    except StopIteration:
        break

此脚本在字符 Å¡ 处出现“UnicodeEncodeError: 'charmap'编解码器无法对第271-272个字符进行编码:该字符映射到<undefined>”的错误。 - Anze

2
通常,这个错误是在创建CSV时引入的。尝试使用Linux将CSV保存为TextCSV格式。Ubuntu中的Libre Office可以强制编码为UTF-8,对我有用。在Mac OS上尝试了很长时间都没成功。Linux是关键。我已在Ubuntu上测试过。
祝好运。

2

执行以下两个步骤:

  1. 需要将您的数据库字符集设置为 utf8

  2. 您需要在连接数据库的文件中调用 mysql_set_charset('utf8'),并在选择数据库后立即使用 mysql_select_dbmysql_set_charset。这将允许您以任何语言正确添加和检索数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接