2012-04-12 19 views
9

Ich erzeuge eine XML-Datei mit PHP mit DomDocument und ich muss mit asiatischen Zeichen umgehen. Ich ziehe Daten vom MSSQL2008-Server mit dem pdo_mssql-Treiber und wende utf8_encode() auf die XML-Attributwerte an. Alles funktioniert gut, solange es keine Sonderzeichen gibt.Encoding SQL_Latin1_General_CP1_CI_AS in UTF-8

Der Server ist MS SQL Server 2008 SP3

Die Datenbank-, Tabellen- und Spaltensortierung werden alle SQL_Latin1_General_CP1_CI_AS

Ich bin mit PHP 5.2.17

Hier mein PDO Objekt ist:

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

Meine Abfrage ist eine grundlegende SELECT.

Ich weiß, Speichern von Sonderzeichen in SQL_Latin1_General_CP1_CI_AS Spalten ist nicht toll, aber im Idealfall wäre es schön, es ohne Änderung zu arbeiten, weil andere Nicht-PHP-Programme bereits diese Spalte verwenden und es funktioniert gut. In SQL Server Management Studio kann ich die asiatischen Zeichen richtig sehen.

Unter Berücksichtigung aller oben genannten Details, wie soll ich die Daten verarbeiten?

+0

Haben Sie ['utf8_encode()'] (http://ca3.php.net/manual/en/function.utf8-encode.php) ausprobiert? Laut Bedienungsanleitung: 'kodiert eine ISO-8859-1-Zeichenfolge zu UTF-8'. –

+0

Natürlich mache ich das gerade, aber die asiatischen Zeichen erscheinen als "?". Selbst wenn ich nur SELECT ausführe und dann die Daten in eine Datei (utf8_encode oder nicht) lege, enden die asiatischen Zeichen als "?" in der Datei. – SGr

+0

Es überrascht mich wirklich, dass Sie tatsächlich asiatische Zeichen in 'LATIN1' kodieren können. 'LATIN1' dient nur zur Kodierung europäischer Zeichen ... –

Antwort

16

Ich fand, wie es zu lösen, so hoffentlich wird dies jemand hilfreich sein.

Erstens ist SQL_Latin1_General_CP1_CI_AS eine seltsame Mischung aus CP-1252 und UTF-8. Die grundlegenden Zeichen sind CP-1252, deshalb musste ich nur UTF-8 machen und alles hat funktioniert. Die asian und andere UTF-8-Zeichen sind auf 2 Bytes kodiert und der php pdo_mssql-Treiber scheint Zeichen unterschiedlicher Länge zu hassen, so dass er CAST zu varchar zu machen scheint (statt nvarchar) und dann alle 2-Byte-Zeichen zu Fragezeichen werden ? ').

ich es fixiert, indem sie auf binäre Gießen und dann wieder aufzubauen ich den Text mit php:

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

in 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); 
+0

für mich nur Casting es binär gearbeitet! danke –

+0

genial !!! perfekt!!! und anerkennende Antwort :) – SagarPPanchal

0

Standardmäßig verwendet PDOPDO::SQLSRV_ENCODING_UTF8 zum Senden/Empfangen von Daten.

Wenn Ihre aktuelle collate LATIN1 ist, haben Sie versucht, folgende Einzelheiten PDO::SQLSRV_ENCODING_SYSTEMPDO wissen zu lassen, dass Sie die aktuelle System-Codierung statt UTF-8 verwenden möchten?

Sie könnten sogar PDO::SQLSRV_ENCODING_BINARY verwenden, die Daten in einer binären Form zurückgibt (beim Übertragen von Daten erfolgt keine Codierung oder Übersetzung). Auf diese Weise können Sie die Zeichencodierung auf Ihrer Seite verarbeiten.

Mehr Dokumentation hier: http://ca3.php.net/manual/en/ref.pdo-sqlsrv.php

+0

Kein' PDO :: SQLSRV_ * 'Parameter funktioniert für mich auf' SQL Server 2008'. Ich bekomme einen Fehler, dass es nicht definiert ist oder so ähnlich. –

2

Ich weiß, dass dieser Beitrag ist alt, aber das einzige, was Arbeit für mich war iconv ("CP850", "UTF-8 // TRANSLIT", $ var); Ich hatte die gleichen Probleme mit SQL_Latin1_General_CP1_CI_AI, vielleicht funktioniert es auch für SQL_Latin1_General_CP1_CI_AS.

2

können Sie versuchen, so:

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>"); 
} 
+1

Dieser arbeitete für mich! Danke: 'print iconv (" CP1252 "," UTF-8 "," $ row [Nome]
");' – joelpittet

0

Dank @SGr für Antwort.
fand ich, dass dafür einen besseren Ausweg:

SELECT CAST(CAST(MY_COLUMN AS VARBINARY(MAX)) AS VARCHAR(MAX)) as MY_COLUMN FROM MY_TABLE;
und auch versuchen, mit:
SELECT CAST(MY_COLUMN AS VARBINARY(MAX)) as MY_COLUMN FROM MY_TABLE;

Und in PHP sollten Sie es nur in UTF-8 konvertieren:

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

0

Für mich war keine der oben genannten die direkte Lösung - obwohl ich Teile der oben genannten Lösungen verwendet habe. Dies funktionierte für mich mit dem vietnamesischen Alphabet. Wenn Sie auf diesen Beitrag und keiner der oben genannten Arbeit für Sie kommen, versuchen Sie:

$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); 
    } 

Und einen kleinen Bonus - ich hatte diese Daten json_encode und war (duh) HTML-Code anstelle der Sonderzeichen zu bekommen. Um zu beheben, verwenden Sie einfach html_entity_decode() für die Strings, bevor Sie mit json_encode senden.