0

我一直在获取此函数检索的名称的 UTF8 版本,但由于某种原因,它没有以正确的字母输出它。

示例输出:

ѕqÃ…ιÑÂтℓє

预期输出:

ѕqυιятℓє 

我已经对文件、从 file_get_contents 中提取的字符串和函数的输出以及源 XML 文件进行了字符集检查。MySQL 也没有得到正确的版本。

此外,SimpleXML 确实支持 UTF-8。

sudo 文件 -i debug.txt

debug.txt: txt/plain; charset=utf-8

MySQL 排序规则

utf8_general_ci

源 XML 文件头

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

这(在代码中两次) -

  $enc = mb_detect_encoding($xml, 'UTF-8', true);
  echo 'Detected encoding '.$enc;

输出:

Detected encoding UTF-8
Detected encoding UTF-8

我不确定在哪里可以检查 UTF-8 字符集,或者这是否是我首先需要做的。我希望这里有人知道如何获得名称的预期版本。提前谢谢。

文本文件(日志)输出函数:

function log_output($message){
  $file = 'debug.txt';
  $current = file_get_contents($file);
  $current .= $message."\n"; 
  file_put_contents($file, $current);  
}

源代码:

// Converts SteamID(64) to the users current name on Steam.
        function steamid64_to_name($steamid64) {
          // Get User Profile Data
          $xml = file_get_contents('http://steamcommunity.com/profiles/'.$steamid64.'/?xml=1');
          $enc = mb_detect_encoding($xml, 'UTF-8', true);
          echo 'Detected encoding '.$enc;
          $xml = simplexml_load_string($xml, null, LIBXML_NOCDATA);
          if(!empty($xml)) {
            if(isset($xml->steamID)) {
               $username = $xml->steamID;// Example: steamcommunity.com/profiles/76561198077095013/?xml=1
            } else { 
              $username = "Username Not Found";
            } 
          } else {
            $username = "User XML Not Found"; // Example: steamcommunity.com/profiles/0/?xml=1
          }
          $enc = mb_detect_encoding($xml, 'UTF-8', true);
          echo 'Detected encoding '.$enc;
          return $username;
        }
4

1 回答 1

0

您所问的不是关于 SimpleXML,而是更多关于您的输出编码。输出编码是您发送到浏览器的数据加上与该数据一起使用的编码信息(数据 + 元数据)。

您还评论说,使用 Apache HTTPDs':

AddDefaultCharset utf-8

为您解决了问题。那就是告诉浏览器您要发送给它的数据是 UTF-8 编码的。之前你告诉浏览器它会是一些拉丁语的东西,因此你得到了这些看起来不正确的字符。只需考虑您需要在信件旁边命名语言,以便收到它的人了解要阅读的信件的语言。

除此之外,您应该考虑一些一般的经验法则,以便更快地发现问题并且不要编写太多代码:

  • 如果您从 a 读取字符串,SimpleXMLElement它将为您提供 UTF-8 编码的数据。无论您创建它的原始文件的编码是什么。
  • SimpleXML 自己处理大部分重新编码,您只需要一个适当的 iconv 安装,这通常是这种情况(否则推荐)。
  • 严格要求自己,永远不要像在此处使用mb_detect_encoding. 这在技术上是不可能的,相反 - 如果编码未知 - 从源而不是从数据中获取该信息(从技术上讲不可能从数据中获取它,这始终是一个猜测)。
  • 最后但并非最不重要的一点是,由于这涉及远程服务,因此您应该始终在此处添加一个间接层。您想在这里介绍的最小的事情是我猜远程请求的缓存,因此将其包装到一个类中是第一步。

您的 Steam API 访问的一些示例:

<?php
/**
 * PHP SimpleXML - Unable to correctly convert SteamID64 to Steam
 * Name with UTF8
 *
 * @link http://stackoverflow.com/q/19507614/367456
 */

$profile = new SteamProfile('76561198027590831');
echo $profile->getUsername(), "\n";
var_dump((string)$profile);

/**
 * Class SteamProfile
 *
 * Converts SteamID(64) to the users current name on Steam.
 */
class SteamProfile
{
    const STEAMAPI_URL_MASK = 'http://steamcommunity.com/profiles/%s/?xml=1';
    const UNKONWN_NAME_MASK = 'User #%s (Username Not Found)';

    private $steamId;
    private $xml;

    public function __construct($steamId)
    {
        $this->steamId = $steamId;
    }

    public function getUsername()
    {
        $xml = $this->getXml($this->steamId);

        return $xml->steamID
            ? (string)$xml->steamID
            : sprintf(self::UNKONWN_NAME_MASK, $this->steamId)
            ;
    }

    private function getXml($steamId)
    {
        if ($this->xml) {
            return $this->xml;
        }

        $url = sprintf(self::STEAMAPI_URL_MASK, $steamId);

        if (!$xml = simplexml_load_file($url)) {
            throw new UnexpectedValueException(sprintf('Unable to load XML from "%s"', $url));
        }

        return $this->xml = $xml;
    }

    public function __toString()
    {
        return sprintf("%s (SteamID: %s)", $this->getUsername(), $this->steamId);
    }
}

示例输出(UTF-8 编码):

ѕqυιятℓє | [A]
string(51) "ѕqυιятℓє | [A] (SteamID: 76561198027590831)"

如示例和输出所示,无需过多关注编码,因为 Steam 提供了有效的 XML,而 Simplexml 是为有效的 XML 制作的。在您的网站上使用 UTF-8 作为编码,或者您需要先将数据从 UTF-8 重新编码为您的目标编码。

此外,通过使用SteamProfile对象,您可以稍后将其替换为不同的实现。例如,将远程请求委托给不同的层。

于 2013-10-30T09:27:04.270 回答