Thread Automatisches decodieren von utf-8 aus mysql Datenbank
(39 answers)
Opened by mcfaq at 2011-08-01 17:55
Hallo pq.
Also ich kannte das Modul Devel::Peek nicht. Ich habe es aber jetzt benutzt und kann dir das Ergebns zeigen. Es ist am Ende des folgenden Quellcodes aufgeführt: Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 #!/usr/bin/perl -w use HTML::Template; use CGI::Simple; use DBI; use Devel::Peek; use CGI::Carp qw(fatalsToBrowser carpout); open(LOG, ">/var/www/utftest/log.txt"); carpout(LOG); use Encode qw( encode decode ); use utf8; binmode(STDIN, ":encoding(utf8)"); #Einem bereits geöffneten Kanal kann nachträglich auch ein Konverter zugewiesen werden_ #binmode(STDOUT, ":encoding(UTF-8)"); my $dbh = DBI->connect( 'DBI:mysql:database=testdb' . ';host=localhost', 'root', 'womex', { RaiseError => 1, Print_warn => 1, Warn => 1, mysql_enable_utf8 => 1} ) or die "Can't connect to database!"; #cgi Objekt für Zugriff auf per GET oder POST erhaltene Formulavariablen my $cgi = new CGI::Simple; #Werte aller Formularelemente in Form eines Hashes my %cgiHash = $cgi->Vars(); # open the html template my $template = HTML::Template->new( filename => 'test.tmpl', utf8 => 1 ); $template->param( spalte => $cgiHash{'input'} ); $template->param( spalte2 => encode('utf-8','5 mal Euro: €€€€€') ); #SQl Statement, welches die Daten der Pflichfelder aus dem Formular speichern läßt. my $sth = $dbh->prepare( qq{ INSERT INTO utftbl SET spalte = ? }); #Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( $cgiHash{'input'} ) ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } my ($return_value) = $dbh->last_insert_id( undef, undef, 'utftbl', 'id' ); $sth = $dbh->prepare( qq{ SELECT spalte from utftbl where id=$return_value }); #Durchführen des selects in die Tabelle mit den Pflichtdaten unless ( $sth->execute() ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } my @arr = $sth->fetchrow_array(); #Wenn Datenbank String als utf-8 kodierter String eingelesen wurde und #wir nichts an diesem verändert haben, dann können wird diesen direkt ohne #Dekodierung/Enkodierung direkt rausschreiben, falls die Ausgabe auch in utf-8 deklariert ist. $template->param( spalte3 => $arr[0] ); $template->param( spalte4 => encode('utf-8',"Präfix€uro:") . $arr[0] ); print( "Content-Type: text/html; charset=UTF-8\n\n", $template->output ); Dump($cgiHash{'input'}); Dump($arr[0]); Dump($template); __END__ SV = PV(0x84b8930) at 0x8488d28 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x84f4aa8 "Das BU\303\242\302\202\302\254RO"\0 [UTF8 "Das BU\x{e2}\x{82}\x{ac}RO"] CUR = 14 LEN = 16 SV = PV(0x84ca9d0) at 0x8532288 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x851c1f0 "Das BU\303\242\302\202\302\254RO"\0 [UTF8 "Das BU\x{e2}\x{82}\x{ac}RO"] CUR = 14 LEN = 16 SV = RV(0x8180df0) at 0x8450788 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x81cbd78 SV = PVHV(0x8158820) at 0x81cbd78 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,SHAREKEYS) IV = 4 NV = 0 STASH = 0x8154744 "HTML::Template" ARRAY = 0x84f4b08 (0:4, 1:4) hash quality = 137.5% KEYS = 4 FILL = 4 MAX = 7 RITER = -1 EITER = 0x0 Elt "param_map" HASH = 0xfaf3dd80 SV = RV(0x8180d24) at 0x852a7f0 REFCNT = 1 FLAGS = (ROK) RV = 0x852a7a8 SV = PVHV(0x85510b0) at 0x852a7a8 REFCNT = 1 FLAGS = (SHAREKEYS,HASKFLAGS) UV = 4 NV = 0 ARRAY = 0x8517b40 (0:5, 1:2, 2:1) hash quality = 91.7% KEYS = 4 FILL = 3 MAX = 7 RITER = -1 EITER = 0x0 Elt "spalte4" [UTF8 "spalte4"] HASH = 0xcf2c47e3 SV = RV(0x8180e48) at 0x8532078 REFCNT = 1 FLAGS = (ROK) RV = 0x8532048 Elt "parse_stack" HASH = 0x4c50ad1 SV = RV(0x8180d1c) at 0x852a808 REFCNT = 1 FLAGS = (ROK) RV = 0x8531b44 SV = PVAV(0x8487eb4) at 0x8531b44 REFCNT = 1 FLAGS = () IV = 0 NV = 0 ARRAY = 0x8361280 FILL = 8 MAX = 11 ARYLEN = 0x852a700 FLAGS = (REAL) Elt No. 0 SV = RV(0x8180e24) at 0x852a5f8 REFCNT = 1 FLAGS = (ROK) RV = 0x821092c Elt No. 1 SV = RV(0x8180e2c) at 0x8531d18 REFCNT = 1 FLAGS = (ROK) RV = 0x8256718 Elt No. 2 SV = RV(0x8180e34) at 0x8531d48 REFCNT = 1 FLAGS = (ROK) RV = 0x8220084 Elt No. 3 SV = RV(0x8180e38) at 0x8531e08 REFCNT = 1 FLAGS = (ROK) RV = 0x8531d00 Elt "options" HASH = 0xa12ff3a2 SV = RV(0x8180c50) at 0x8488d1c REFCNT = 1 FLAGS = (ROK) RV = 0x8488e24 SV = PVHV(0x84d8568) at 0x8488e24 REFCNT = 1 FLAGS = (SHAREKEYS,HASKFLAGS) UV = 33 NV = 0 ARRAY = 0x851a8c0 (0:37, 1:22, 2:4, 3:1) hash quality = 105.3% KEYS = 33 FILL = 27 MAX = 63 RITER = -1 EITER = 0x0 Elt "cache_debug" HASH = 0x3cb23b45 SV = IV(0x8480070) at 0x848e8a8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 0 In diesem veränderten und kürzeren Quellcode wird durch weglassen einer der "utf8 Anweisungen" das Ergebnis wieder falsch. Ich habe folgende Schlüsse gezogen. A) Wenn ich binmode(STDIN, ":encoding(utf8)"); weglasse, dann: * erhalte ich folgende Warnung im LOG -> Quote * Alle Euros außer die aus der DB Tabelle werden falsch dargestellt: nämlich so ⬠B1.1) Wenn ich , mysql_enable_utf8 => 1 weglasse, dann: * werden nur die Euros aus der DB Tabelle falsch dargestellt: nämlich so ⬠B1.2) Wenn ich zusätzlich zu Wegnahme , mysql_enable_utf8 => 1 noch $arr[0] = decode('utf-8',$arr[0]) hinter my @arr = $sth->fetchrow_array(); einfüge, dann klappt es wieder fehlerfrei. B1.3) Wenn ich dann noch zusätzlich $template->param( spalte4 => encode('utf-8',"Präfix€uro:") . $arr[0] ); in $template->param( spalte4 => ,"Präfix€uro:" . $arr[0] ) , dann: * erhalte ich folgende Warnung im LOG -> [/quote][Tue Aug 2 16:35:21 2011] form.cgi: Wide character in print at /var/www/utftest/form.cgi line 73.[quote] * es wird nur der Euro, welches direkt im Perl Program steht richtig ausgegeben und ansonsten ⬠angezeigt. C) Wenn ich , utf8 => 1 entferne: * passiert nichts -> alles bleibt korrekt. Ich hoffe jemandem fällt ein Weg ein, wie man gelesene Ergebnisse aus der mysql DB Tabelle in dekodierter Form erhält, ohne explizit decode anwenden zu müssen. Nochmal zur Verdeutlichung. Hier in diesem Beispiel mag es ja nicht erforderlich zu sein, da man ja auch utf-8 Strings konkatinieren kann und den Ergebnis Utf-8 String in template schreiben kann. Mir geht es aber darum, dass ich auch andere String Funtionen, welche nicht auf Binärstrings korrekt arbeiten , wie z.B. length uc lc ..., anwenden zu können. Ich will also den String in der überwiegenden Zeit der Programmausführung in dekodierter Form haben. Gruß mcfaq. modedit Editiert von pq: Teilbaum "HTML::Template und utf-8", da der mysql-Teil korrekt ist Last edited: 2011-08-02 18:10:26 +0200 (CEST) |