【问题标题】:Encoding string with non-ascii characters用非 ASCII 字符编码字符串
【发布时间】:2015-01-24 22:38:07
【问题描述】:

我有一个这样的字符串 - Panamá。我需要将此字符串转换为Panam\xE1,以便它可以在我使用PHP 生成的JavaScript 文件中读取。

有没有一个函数可以在 PHP 中对此进行编码?任何想法将不胜感激。

【问题讨论】:

  • 除了您使用的 ASCII 之外,是否还有其他元格式,例如JSON 还是 XML?有了这些,您可以将适当的传输(包括编码/解码和转义/取消转义)委托给相应的元格式库,这比滚动您自己的东西更可取。

标签: php hex encode


【解决方案1】:

我的原则是,

如果您尝试使用 preg_replace 对数据进行编码或转义,或者 使用海量映射数组str_replaceSTOP你可能做错了。

只需要一个丢失或错误的映射(你会错过一些映射),然后你会得到在所有情况下都不起作用的代码以及在某些情况下会破坏你的数据的代码.已经编写了整个库,专门用于为您进行翻译(例如 iconv)和转义数据,您应该使用正确的 PHP 函数。

如果您打算将数据输出到浏览器(您想要为 javascript 编码的事实表明了这一点),那么我建议使用 UTF8 编码。如果您的数据是 latin-1 格式,请使用 utf8_encode 函数。

无论您的 PHP 字符串是否包含 ASCII 字符,要将任何数据从 PHP 发送到 JS,您都应该始终 use the json_encode function

PHP 代码

$your_encoding = 'latin1';
$panama = "Panamá";

//Get your data in utf8 if it isnt already
$panama = iconv($your_encoding, "utf-8", $panama);

$panama_encoded = json_encode($panama);
echo "var js_panama = " . $panama_encoded . ";";

JS 输出

var js_panama = "Panam\u00e1";

即使 JSON 支持 unicode,它也可能与您的非 UTF-8 javascript 文件不兼容。这不是问题,因为 json_encode PHP 函数默认会转义 unicode 字符。

【讨论】:

  • 您确实意识到json_encode 仅适用于 UTF-8 输入,对吧?
  • 好吧,我做了一个假设,但如果您是 PHP 开发人员(或与一般网站打交道),UTF-8 应该是您的编码。如果您正在从其他地方读取不是 utf8 的字符串,那么只需使用 utf8_encode。但是谢谢,我会在回答中更清楚地说明这一点。
  • utf8_encode also 假定输入编码,所以它绝对没有给你任何关于一般性的信息。实际上,在可以使用utf8_encode 的情况下,也可以使用带有替换的“手动”解决方案。
  • @Jon 你是绝对正确的。但我从未打算创建一个适用于任何编码的神奇解决方案。正如您所指出的,这是不可能的。但这种方法也进一步解决了 XSS 攻击等安全问题,并且不使用凌乱的 preg_replace 或 str_replace。您的解决方案将起作用,但我觉得这种方式是将数据输入 javascript 的更好方法。我添加了 iconv 而不是 utf8_encode 以便 OP 可以指定编码。也许我的观点现在更清楚了。
【解决方案2】:

假设您的输入是 latin-1 编码,那么 orddechex 将执行您想要的操作:

$result = preg_replace_callback(
    '/[\x80-\xff]/',
    function($match) {
        return '\x'.dechex(ord($match[0]));
    },
    $input);

如果您的输入采用任何其他编码,那么您需要知道是什么编码并相应地调整解决方案。请注意,在这种情况下,不可能在所有情况下都在 JS 输出中专门使用 \x## 表示法。

【讨论】:

  • 这里只是一个小错误:$m[0]-> $match[0]
  • @Rizier123:谢谢,已修复。
  • 如果它们不在 latin-1 编码中呢?有没有办法检查所有的?
  • @Lex:你必须知道你输入的编码是什么(或者只是随意声明你只接受编码 X 和/或 Y)。 It is not possible to guess and be consistently correct.
  • @Phil_1984_:很抱歉这么说,但你不知道你在说什么。
【解决方案3】:

这应该适合你:

$str = "Panamá";
$str = preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($m) {
    $utf = iconv('UTF-8', 'UCS-4', current($m));
    return sprintf("\x%s", ltrim(strtoupper(bin2hex($utf)), "0"));
}, $str);

echo $str;

输出(源代码):

Panam\xE1

【讨论】:

  • JavaScript 中的 \x 表示法仅适用于 latin-1 编码。尝试对 U+FF 以上的 Unicode 码位进行编码是没有意义的。
  • 这对所有非A​​SCII字符都有效吗?比如á、í、é、ó、ü、ú、ñ等?
  • @Lex 只需测试一下,你就会看到它:D(例如 Panamáá, í, é, ó, ü, ú, ñ => Panam\xE1\xE1, \xED, \xE9, \xF3, \xFC, \xFA, \xF1
  • @Lex 如您所见,它有效 ^,您的问题是否得到解答或您需要什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
  • 2014-01-07
  • 2014-07-16
相关资源
最近更新 更多