2009-06-11 6 views
11

Meine delicious-to-wp perl script funktioniert aber gibt für alle "komischen" Zeichen noch seltsamer Ausgabe. Also habe ich versuchtWie kann ich mit Unicode Perls DBI umgehen?

$description = decode_utf8($description); 

aber das tut einen Unterschied machen. Ich möchte z.B. "Go live" um "live" zu werden und nicht "live" Wie kann ich in Perl mit Unicode umgehen, damit das funktioniert?

UPDATE: Ich fand das Problem utf von DBI zu setzen war ich in Perl gesetzt hatte:

my $sql = qq{SET NAMES 'utf8';}; 
$dbh->do($sql); 

, dass der Teil war, dass ich, heikel gesetzt hatte. Vielen Dank!

+0

Destillieren Sie Ihren Code zu dem kürzest möglichen Skript, das immer noch das Problem aufweist. Nehmen Sie die Datenbank aus der Gleichung, um herauszufinden, ob das Problem mit Perl zu tun hat. Stellen Sie sich etwas vor, was andere testen und debuggen können. –

Antwort

3

Es kann nichts mit Perl zu tun haben. Stellen Sie sicher, dass Sie UTF-Codierungen in den entsprechenden MySQL-Tabellenspalten verwenden.

+0

Die Tabellen waren in UTF, aber ich musste die Set-Namen zum DBI in Perl hinzufügen ... – edelwater

17

Es ist erwähnenswert, dass, wenn Sie eine Version von DBD :: mysql neu genug (3.0008 an) ausführen, können Sie Folgendes tun: $dbh->{'mysql_enable_utf8'} = 1; und dann alles decode() ed/encode() ed für Sie auf der Ausweg von/nach DBI.

+5

Für die Faulenzer wie mich ist dies die dbic-Variante: Schema-> connect ("dbi: mysql:". $ Db { db}, $ db {Benutzer}, $ db {pass}, {mysql_enable_utf8 => 1}); –

+0

Lösung in der Antwort funktioniert nicht für mich, aber Lösung in der obigen Kommentar von @al. klappt wunderbar. –

3

Der Begriff

$dbh->do(qq{SET NAMES 'utf8';}); 

auf jeden Fall den Tag spart für eine utf-8 erklärt Datenbank zugreifen, aber zur Kenntnis nehmen, wenn Sie keine Perl Verarbeitung von alle Daten aus dem db obatined tun werden würde es Es ist ratsam, es in einer Perl-Variablen als utf8-String zu speichern, da diese Operation nicht implizit ist.

$utfstring = decode('utf8',$string_from_db); 

natürlich für die richtige i/o Umgang mit UTF-8-Zeichenketten (Lesen, Drucken, um die Ausgabe geschrieben wird) erinnern

einstellen
use open ':utf8'; 

und

binmode STDOUT, ":utf8"; 

letztere wesentlich ist zum Ausdrucken von utf8-Strings. Hoffe das hilft.

+0

Wie bekomme ich die Dekodierfunktion? Perl zeigt einen Fehler an und sagt, dass die Routine decode() nicht gefunden werden kann. Vielen Dank! – Arsenii

+0

Das behebt mein Problem..Have ein Perl-CGI-Skript, das eine Verbindung zu einer Postgre utf-8-Datenbank herstellt, die eine JSON-Zeichenfolge mit XHR an den Client zurückgibt. Die Zeichen wurden auf der Client-Seite angezeigt, bis sie "mein $ final_utf8 = Encode :: encode_utf8 ($ treeJSON)" hinzugefügt haben. print CGI-> Kopfzeile ('application/json; charset = UTF-8'); Drucken Sie "$ final_utf8"; 'wie in Ihrem Post vorgeschlagen. Denken Sie daran, dass Sie 'use Encode;' oben im Perl-Skript verwenden müssen, um dies zu verwenden. – GoinOff

1

Lassen Sie dieses heraus:

binmode STDOUT, ":utf8"; 

bei der Verwendung von:

$dbh->do(qq{SET NAMES 'utf8';}); 

Andernfalls wird Ihr Ausgangsdoppel UTF8-Codierung haben, in unlesbaren Double-Byte-Zeichen führen! Es dauerte ein paar Stunden, um dies herauszufinden ..

+0

Wenn das, was Sie sagen, wahr ist, dann weiß Perl nicht, dass die aus der Datenbank abgerufenen Daten UTF-8-kodiert sind und denkt einfach, dass es Bytes sind. Sicherlich DBD :: Mysql (oder was auch immer DBD Sie verwenden) entschlüsselt die Daten aus der Datenbank für Sie in diesem Fall Perl sollte wissen, dass Sie Unicode-Zeichen haben und wenn sie mit der utf8-Ebene in stdout geschrieben werden, wird alles gut. Wenn das, was du beschreibst, passiert, würde ich vorschlagen, dass deine DBD kaputt ist. Betrachtet man jedoch das neueste DBD :: Mysql, dann tut es "sv_utf8_decode (sv);" zumindest bei einigen Daten. – bohica

+0

Bohica, DBD :: mysql bietet normalerweise Bytes, [implizite Decodierung] (http://p3rl.org/DBD::mysql#mysql_enable_utf8) ist nicht standardmäßig aktiviert. – daxim

11

UTF8 aktivieren, wenn Sie auf die Datenbank wie folgt verbinden:

my $dbh = DBI->connect(
    "dbi:mysql:dbname=db_name", 
    "db_user", "db_pass", 
    {RaiseError => 0, PrintError => 0, mysql_enable_utf8 => 1} 
) or die "Connect to database failed."; 

Dies sollten Sie Zeichenmodus Strings mit dem UTF8-Flag gesetzt bekommen je nach Bedarf .

Von DBI General Interface Rules & Caveats:

Perl unterstützt zwei Arten von Strings: Unicode (UTF-8-intern) und Nicht-Unicode (Standard: iso-8859-1, wenn gezwungen, eine Codierung übernehmen).Treiber sollten beide Arten von Zeichenfolgen akzeptieren und bei Bedarf in den Zeichensatz der verwendeten Datenbank konvertieren. In ähnlicher Weise sollte der Treiber, wenn er aus der Datenbank Zeichendaten, die nicht iso-8859-1 sind, in utf8 konvertieren.

Und die Besonderheiten von DBD::mysql für mysql_enable_utf8

Zusätzlich zu dieser Flagge Drehen sagt MySQL, dass eingehende Daten als UTF-8 behandelt werden sollten. Dies wird nur wirksam, wenn Sie als Teil des Aufrufs von connect() verwendet werden. Wenn Sie das Flag nach dem Verbinden einschalten, müssen Sie den Befehl SET NAMES utf8 ausführen, um denselben Effekt zu erhalten.

0

standardmäßig der Fahrer Perl/MySQL behandelt Binärdaten (zumindest schloss ich dies von einigen Experimenten mit MySQL 5.1 und 5.5).

Ohne mysql_enable_utf8 zu setzen, habe ich die Strings zu/von UTF-8 codiert/entschlüsselt, bevor ich in die Datenbank geschrieben/gelesen habe.

Es sollte nicht auf die perl-interne Zeichenfolgendarstellung als Array von Byte verlassen werden; Beachten Sie, dass das interne 'utf8' nicht garantiert Standard-UTF-8 ist; Umgekehrt ist die Einzelbyte-Codierung nicht garantiert ISO-8859-1; wirklich kodieren/entschlüsseln zu/von UTF-8 (und nicht 'utf8').

Es gibt auch einige Einstellungen von MySQL (wie SET NAMES oben, soweit ich mich erinnere, gibt es eine Client-Kodierung, eine Verbindungskodierung und eine Serverkodierung, deren Interaktionen mir nicht ganz klar sind, wenn sie nicht alle haben haben den gleichen Wert) bezüglich der Kodierungen; sie alle auf UTF-8 zu setzen, und das obige Rezept funktionierte für mich.