【问题标题】:iconv with ascii // transit triggers ErrorException: "iconv(): Detected an illegal character in input string"iconv with ascii // 传输触发 ErrorException: "iconv(): Detected an invalid character in input string"
【发布时间】:2014-03-09 07:06:09
【问题描述】:

首先,我不得不说;我是多语言转换的陌生人。

我有字符串,如果可能的话,我想以 UTF-8 格式转换为 mb_lowercase(比如干净的 url),我使用

$str = iconv("UTF-8", "ASCII//TRANSLIT", utf8_encode($str));
$str = preg_replace("/[^a-zA-Z0-9_]/", "", $str);
$str = mb_strtolower($str);

满足我的要求(UTF8,小写字符串)

但是,当我使用 CocoaRestClient 使用“çokGüŞelLl”强调该功能时;我得到 à as $str(感谢我的客户?)并且 iconv 触发错误,抱怨输入字符串 (Ã) 中有非法字符。

iconv 有什么问题? str 已经被utf8_encode($str) 编码为utf8。怎么可能是非法字符?

注意事项: 我在这里阅读了有关@iconv 的问题,但我认为拥有空数据库条目并不是一个好的解决方案。


感谢所有答案,我会阅读并尝试理解它们。

【问题讨论】:

  • 您的输入不是 UTF-8。如果您真的使用utf_encode() 创建它,那么您的原始文本可能不是ISO-8859-1。
  • 我的输入 ÇokGüŞelLl 是 UTF 8(在 MySQL 中也保存了 UTF8-general),返回结果也是一样的。但是我不知道那件事。我也在实际代码中使用了确切的代码。
  • 如果您将数据存储为 UTF-8,而您需要数据为 UTF-8,为什么要从 ISO-8859-1 转换?您可以使用bin2hex 了解您的实际字节数。
  • 他们的键盘不任何东西,浏览器以编码方式提交它,所有现代浏览器都默认为utf-8,除非你用@改变它987654325@ 表单上的属性。
  • 例如 Drupal 总是将 accept-charset 设置为 UTF-8,如果您的用户使用完全损坏的客户端,您也可以这样做。

标签: php iconv


【解决方案1】:

PHP 函数utf8_encode() 期望您的字符串是ISO-8859-1 编码的。如果不是,那么你会得到有趣的结果。

确保您的数据是正确的 UTF-8 保存到您的数据库之前:

// Validate that the input string is valid UTF-8
if (preg_match("//u", $string) === false) {
    throw new \InvalidArgumentException("String contains invalid UTF-8 characters.");
}

// Normalize to Unicode NFC form (recommended by W3C)
$string = \Normalizer::normalize($string);

现在所有内容都以相同的方式存储在我们的数据库中,当从我们的数据库接收数据时,我们不必再关心这个问题了。

$string = $database->getSomeRecordWithUnicode();

echo mb_strtolower($string);

完成!

PS:如果您想确保您的数据库使用与 PHP 完全相同的编码,请使用 utf8mb4 作为字符集(并使用 utf8mb4_unicode_ci 作为完美排序的默认排序规则)或 BLOB(二进制)数据输入。

PPS:使用您的数据库配置文件强制对所有字符串进行正确编码,而不是使用例如$mysqli->set_charset("utf8") 或类似的。

关于 HTML 表单

因为您在问题的 cmets 中提出了问题。数据如何发送到您的服务器与用户在其操作系统中设置的语言环境无关。它与客户端的浏览器有关。所有现代浏览器在发送表单数据时默认为utf-8。如果您担心您的某些客户可能使用完全损坏的浏览器,只需告诉他们您只接受utf-8。 Drupal 在所有表单上都这样做。

<!doctype html>
<html>
<body>
    <form accept-charset="UTF-8">

现在所有浏览器都应该对他们在utf-8中提交的数据进行编码。

【讨论】:

    【解决方案2】:

    如果您将çokGüŞelLl 编码为 UTF-8,您应该得到以下字节:

    var_dump( bin2hex('çokGüŞelLl') );
    
    string(26) "c3a76f6b47c3bcc59e656c4c6c"
    

    这是您必须做的检查。你也有这个:

    utf8_encode($str)
    

    您的字符串包含Ş,它无法以 ISO-8859-1 开头。

    因此,无论出于何种原因,您必须将原始 UTF-8(存储在 DB 中)转换为 ISO-8859-1,恐怕它会损坏您的数据。

    【讨论】:

    • 它是 preg_match_all()。将正则表达式从 '/(?:^|\s)\#\pL+/' 更改为 '/(*UTF8)(?:^|\s)\#\pL+/' 解决了我的问题。感谢您照亮我的道路。
    【解决方案3】:

    你是双重编码。首先,您将数据库设置为 UTF-8。这意味着您的数据现在是 UTF-8 编码的。然后在 iconv 函数上使用 utf8_encode。但是您的输入已经是 UTF-8。尝试从 iconv 中删除您的 utf8_encode 语句。

    【讨论】:

    • 当我这样做时; iconv 触发另一个异常。 (我也在 stackoverflow 找到了解决方案)。另请注意,我已经将源代码保存为 UTF-8
    • 删除时错误为“检测到输入字符串中的不完整多字节字符”。
    • 我不是双重编码。是 preg_match_all() 改变了编码。但感谢您提及该领域。
    猜你喜欢
    • 2012-10-29
    • 2014-09-19
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2012-07-03
    • 2022-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多