Вопрос по xml, php, sql-server-2008, encoding – Кодирование SQL_Latin1_General_CP1_CI_AS в UTF-8

11

Я создаю XML-файл с помощью PHP, используя DomDocument, и мне нужно обрабатывать азиатские символы. Я извлекаю данные с сервера MSSQL2008 с помощью драйвера pdo_mssql и применяю utf8_encode () к значениям атрибута XML. Все работает нормально, пока нет специальных символов.

Сервер MS SQL Server 2008 SP3

База данных, таблица и столбец сортировки все SQL_Latin1_General_CP1_CI_AS

Я использую PHP 5.2.17

Вот мой объект PDO:

<code>$pdo = new PDO("mssql:host=MyServer,1433;dbname=MyDatabase", user123, password123);
</code>

Мой запрос является основным SELECT.

Я знаю, что хранить специальные символы в столбцах SQL_Latin1_General_CP1_CI_AS не очень хорошо, но в идеале было бы неплохо заставить его работать без его изменения, потому что другие не-PHP программы уже используют этот столбец, и он работает нормально. В SQL Server Management Studio я правильно вижу азиатские символы.

Учитывая все вышеизложенное, как мне обрабатывать данные?

Меня действительно удивляет, что вы на самом деле можете кодировать азиатские символы вLATIN1. LATIN1 только для кодирования европейских символов ... Pierre-Olivier
Ты пыталсяutf8_encode() ? Согласно инструкции:Encodes an ISO-8859-1 string to UTF-8. Pierre-Olivier
Конечно, это то, что я сейчас делаю, но азиатские символы отображаются как «?». Даже если я просто запускаю SELECT, а затем помещаю данные в файл (utf8_encode или нет), азиатские символы заканчиваются как & quot; в файле. SGr

Ваш Ответ

6   ответов
2

что этот пост старый, но единственное, что работает для меня, было iconv ("CP850", "UTF-8 // TRANSLIT", $ var); У меня были те же проблемы с SQL_Latin1_General_CP1_CI_AI, возможно, это работает и для SQL_Latin1_General_CP1_CI_AS.

0

я и использовал части вышеупомянутых решений. Это работало для меня с вьетнамским алфавитом. Если вы сталкиваетесь с этим постом и ни одно из вышеперечисленного не работает для вас, попробуйте:

    $req = "SELECT CAST(MY_COLUMN as VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE"; 
    $stmt = $conn->prepare($req);
    $stmt->execute();
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $str = pack("H*",$row['MY_COLUMN']);
        $str = mb_convert_encoding($z, 'HTML-ENTITIES','UCS-2LE');
        print_r($str);
    }

И небольшой бонус - мне пришлось json_encode эти данные и (да) получать html-код вместо специальных символов. чтобы исправить это, просто используйте html_entity_decode () для строк перед отправкой с помощью json_encode.

0

PDO использованияPDO::SQLSRV_ENCODING_UTF8 для отправки / получения данных.

Если ваш текущий сборникLATIN1Вы пробовали указатьPDO::SQLSRV_ENCODING_SYSTEM позволитьPDO знать, что вы хотите использовать текущую кодировку системы вместоUTF-8 ?

Вы могли бы даже использоватьPDO::SQLSRV_ENCODING_BINARY который возвращает данные в двоичном виде (при передаче данных не выполняется кодирование или перевод). Таким образом, вы можете обрабатывать кодировку символов на своей стороне.

Больше документации здесь:http://ca3.php.net/manual/en/ref.pdo-sqlsrv.php

Ни один изPDO::SQLSRV_* параметры работают для меня наSQL server 2008, Я получаю какую-то ошибку, что она не определена или что-то в этом роде.
21

Во-первых, SQL_Latin1_General_CP1_CI_AS - это странное сочетание CP-1252 и UTF-8. Базовые символы - CP-1252, поэтому все, что мне нужно было сделать, это UTF-8, и все заработало. Азиатские и другие символы UTF-8 кодируются в 2 байта, и драйвер php pdo_mssql, похоже, ненавидит символы различной длины, поэтому он, похоже, делает CAST для varchar (вместо nvarchar), а затем все 2-байтовые символы становятся знаками вопроса (& apos ;? & APOS;).

Я исправил это, переведя его в двоичный файл, а затем перестроил текст с помощью php:

SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) FROM MY_TABLE;

В php:

//Binary to hexadecimal
$hex = bin2hex($bin);

//And then from hex to string
$str = "";
for ($i=0;$i<strlen($hex) -1;$i+=2)
{
    $str .= chr(hexdec($hex[$i].$hex[$i+1]));
}
//And then from UCS-2LE/SQL_Latin1_General_CP1_CI_AS (that's the column format in the DB) to UTF-8
$str = iconv('UCS-2LE', 'UTF-8', $str);
для меня только приведение к бинарности сработало! Спасибо
классно!!! идеально!!! и благодарный ответ :)
но ... но ... это умственно. Неужели нет лучшего способа?mb_convert_encoding
0

Спасибо @SGr за ответ.
Я нашел лучший способ сделать это:

SELECT CAST(CAST(MY_COLUMN AS VARBINARY(MAX)) AS VARCHAR(MAX)) as MY_COLUMN FROM MY_TABLE;
а также попробуйте с:
SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE;

А в PHP вы должны просто преобразовать его в UTF-8:

$string = iconv('UCS-2LE', 'UTF-8', $row['MY_COLUMN']);

2

header("Content-Type: text/html; charset=utf-8");
$dbhost   = "hostname";
$db       = "database";
$query = "SELECT *
    FROM Estado
    ORDER BY Nome";
$conn = new PDO( "sqlsrv:server=$dbhost ; Database = $db", "", "" );
$stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED, PDO::SQLSRV_ENCODING_SYSTEM) );
$stmt->execute();
while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) )
{
// CP1252 == code page Latin1
print iconv("CP1252", "ISO-8859-1", "$row[Nome] <br>");
}
Этот работал для меня! Спасибо:print iconv("CP1252", "UTF-8", "$row[Nome] <br>");

Похожие вопросы