Peter Rehm's Blog

apple,development,life & more

Weitere Lektion in der Umlautproblematik

Mit 2 Kommentaren

Nachdem ich in einem früheren Blog Eintrag empfohlen habe, alle Daten aus
Speicherplatzgründen die im UTF-8 Format sind in z.b. dem latin1 charset abzulegen,
muss ich dem nun komplett wiedersprechen.
Bei einem durchschnittlichen Projekt lädt man sich deutlich mehr Ärger auf,
als dass man dadurch Vorteile durch Speicherplatzersparnis erzielt.

In meiner Situation sah das dann so aus, dass ich ca. 8 Stunden damit beschäftigt
war, alle Datenbanken meiner Kunden umzustellen, was enorm händische Arbeit
erforderte.

Im Ist-Zustand war es nun auch so, dass mittels phpMyAdmin logischerweise
alle Umlaute kaputt angezeigt wurde, und man nicht oder nur mit hohem manuellen
Aufwand direkt die Daten bearbeiten konnte.

Ausgangssituation
Datenbank mit latin1 als Standardcharset, alle Tabellen latin1, und UTF-8 Daten darin gespeichert.

Ziel
Datenbank & Tabellen UTF-8, und alle Inhalte UTF-8
Ich habe mich für utf8_general_ci entschieden, der unterschied zu utf8_unicode_ci liegt nur in
der Abhandlung von Sortierreihenfolgen. Dies kann man aber im Detail dem MySQL Manual entnehmen.

1.) Datenbank Backup erstellen
Gehen wir einfach mal auf nummer sicher, um die Daten auch sicher nicht
endgültig zu zerstören.

2.) Umwandeln aller Tabellen voll automatisch, und davon sollen auch alle
Text und Varchar Felder umgewandelt werden. Manch einer wird hier noch anpassungen
vornehmen müssen, da ich keine Char Felder umwandle, da die nicht benötigt
werden. ACHTUNG! Das Script basiert wie alle meine Code Snippets auf adodb,
kann aber Problemlos auf die von MySQL zur Verfügung stehenden Funktionen
portiert werden.

CODE:
<?php
// fetch all tables
$data = $cfg['db']->pExecute("SHOW
TABLES");
while($row = $data->FetchRow())
{
$sres = $cfg['db']->pExecute("DESCRIBE ".($row[0]));
while( $column = $sres->FetchRow())
{
// if column is text or varchar, convert
if(strpos($column['Type'],'text')!==false || strpos($column['Type'],'char')!==false
|| strpos($column['Type'],'varchar')!==false)
{
$cfg['db']->Execute("ALTER TABLE ".($row[0])." CHANGE ".($column['Field'])." ".($column['Field'])." ".($column['Type'])." CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
}
}

// confert now also full table
$cfg['db']->Execute("ALTER TABLE ".$row[0]." DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
}
?>


3.) Manuelles Umwandeln der Datenbank
Ich habe mich dazu entschieden die eigentliche Datenbank händisch umzuwandeln,
da ich mich eh mit der Datenbank verbinden musste. Dazu habe ich dann folgendes
SQL Statement eingegebn

CODE:
ALTER DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci


4.) Exportieren der Daten
Nun werden die Daten der kompletten Datenbank exportiert, nicht aber die
Struktur. Dies wird für die meisten am besten mittels einer grafischen Oberfläche
wie phpMyAdmin erledigt. Hier kann man dies mit weigen Mausklicks erreichen.

5.) Umwandeln des Datendumps
Nun wandeln wir einfach noch die "kaputten Zeichen" zurück in UTF8.
In meinem Fall und in den meisten wird folgendes Script hinreichend sein.
Dazu muss eine Datei data.sql im gleichen Verzeichnis wie das eigentliche
PHP Skript sein.

CODE:
<?php
$str=file_get_contents('data.sql');

$bad_char=array("ä","ö","ü","Ä","Ö","Ü","ß");
$right=array('ä','ö','ü','Ä','Ö','Ü','ß');

$bla=str_replace($bad_char,$right,$str);

echo $bla;

?>


6.) Abschließende Arbeiten
Um die ganze Aktion abzuschließen, muss nur noch die Datenbank geleert werden,
un der neue Dump eingelesen werden. Dann sollte man die Umlaute alle
im entsprechenden Format in der Datenbank haben.

Nun werden einige aber sicher zerstörte Umlaute in der Ausgabe haben,
und sich wundern warum. Dies liegt an der MySQL Verbindung die einen
Befehl zu beginn benötigt um UTF8 sauber zu behandeln.

CODE:
$cfg['db']->Execute("SET names utf8");


Nun sollte es endlich geschafft sein, und man sollte sich nun hoffentlich
wieder wichtigeren Dingen widmen können :-)

Achja, heikel ist dann auch das string handling an manchen stellen, daher sollte man auf
die mb_* funktionen von PHP zurückgreifen.


Geschrieben von Peter Rehm

16.08.2007 um 02:38:50

Abgelegt in PHP

Tags für diesen Artikel: , ,

Erkenntnis des Tages

Ohne Kommentare

Mein MacBookPro ist einfach zu schnell um zu messen wie lange eine Zuweisungs oder eine Rechenoperation dauert :-) Resultat, komplett belegter Ram der mich zu einem Neustart zwang und die Erkenntnis dass 1000000 Zuweisungsoperationen weniger als 0,01 sekunden brauchen.

Juhuu!

Geschrieben von Peter Rehm

26.12.2006 um 21:07:08

Abgelegt in Programmierung

Tags für diesen Artikel: ,

Performancetests / Profiling in C

Ohne Kommentare

Dies musste ich heute einsetzen beim Testen eines Sortieralgorithmus.

Man compiliere sein Programm wie folgt:

CODE:
gcc -o ex1b -pg -ansi ex1b.c


Danach muss das Programm einmal ausgeführt werden

CODE:
./ex1b


Danach kann man sich direkt die Profiling Informationen anzeigen lassen, in meinem Fall:

CODE:
gprof ./ex1b


CODE:
granularity: each sample hit covers 4 byte(s) for 0.81% of 1.23 seconds

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 91.9       1.13     1.13        1  1130.00  1130.00  _ins_sort [3]
  2.4       1.16     0.03                             ___sfvwrite [4]
  1.6       1.18     0.02        2    10.00    10.00  _print_array [5]
  1.6       1.20     0.02                             _write [6]
  0.8       1.21     0.01                             ___vfprintf [7]
  0.8       1.22     0.01                             _localeconv_l [8]
  0.8       1.23     0.01                             _printf [9]
  0.0       1.23     0.00        1     0.00     0.00  _create_random_array [39]
  0.0       1.23     0.00        1     0.00  1150.00  _main [1]


Index by function name

   [4] ___sfvwrite           [3] _ins_sort             [5] _print_array       
   [7] ___vfprintf           [8] _localeconv_l         [9] _printf            
  [39] _create_random_arra   [1] _main                 [6] _write 

Geschrieben von Peter Rehm

01.12.2006 um 13:54:34

Abgelegt in Programmierung

Tags für diesen Artikel: , ,

malloc in C

Mit 2 Kommentaren

Die Erkenntnis des Tages: Manche Fehler sind echt dumm!!

Zur Erklärung:

Bei der Fehlermeldung

CODE:
structfun.c:41: warning: incompatible implicit declaration of built-in function 'malloc'


kommt man schnell zu einem Truschluss. Der Fehler befindet sich nicht in der Zeile 41
sondern liegt einfach an der Header Datei.

CODE:
#include <stdlib.h>


Damit sollte das Problem erledigt sein :-)

Geschrieben von Peter Rehm

27.11.2006 um 17:52:35

Abgelegt in Programmierung

Tags für diesen Artikel: , , ,