Thread Automatisches decodieren von utf-8 aus mysql Datenbank (39 answers)
Opened by mcfaq at 2011-08-01 17:55

mcfaq
 2011-08-02 17:12
#150970 #150970
User since
2011-04-20
20 Artikel
BenutzerIn
[default_avatar]
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
[Tue Aug 2 16:29:11 2011] form.cgi: Wide character in print at /var/www/utftest/form.cgi line 74.

* 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)

View full thread Automatisches decodieren von utf-8 aus mysql Datenbank