Peter Rehm's Blog

apple,development,life & more

jpgraph und utf-8 daten

Mit 6 Kommentaren

Wer sich wundert wieso die Texte der erzeugten Graphen mittels jpgraph
in kryptischen Buchstaben dargestellt werden, obwohl gültige Daten in UTF-8
angeliefert wurden, ist nur einen kleinen Schritt von der Lösung entfernt.

Die Ursache des Problems liegt darin dass die Standardschriftarten von jpgraph
kein UTF-8 darstellen können.

Daher kann man sich einfach wie auch auf der jpgraph Seite angegeben ein
entsprechendes Schriftpaket herunterladen. Ich hab mich in meinem Fall für
Verda entschieden.Dies bekommt man hier: http://www.gnome.org/fonts/

Die Schirften lädt man sich herunter und lädt Sie in ein beliebiges Verzeichnis.

Nun muss nur noch das Verzeichnis der Library bekannt gemacht werden:

CODE:
DEFINE("TTF_DIR",dirname(_file_) . '/../../ttf-bitstream-vera-1.10/');


Nun muss man noch mittels SetFont angeben, wo welche Schrift eingesetzt werden
soll. Mir ist es allerdings nicht gelungen die Schriftart für die Beschriftung in den
Netzdiagrammen (jpgraph_radar.php) festzulegen, daher musste ich manuell
die Standardschrift ändern, indem ich in jpgraph.php und jpgraph_radar.php FF_FONT1
durch FF_VERA ersetzt habe.

Nun sollten alle Umlaute auch angezeigt werden können.

Geschrieben von Peter Rehm

01.10.2007 um 23:35:00

Abgelegt in PHP

Tags für diesen Artikel: , ,

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: , ,

Komische Zeichen in UTF8 aka BOM (Byte order Mark)

Ohne Kommentare

Schon lange hab ich mich über die "komischen" Zeichen geärgert, die der Texteditor meines Vertrauens BBEdit am Anfang jeder UTF-8 Datei eingefügt hat. Ich hab dann sogar andere Texteditoren engesetzt, und irgendwie hatte ich immer das gleiche Problem.

Vor allem war ärgerlich, dass ich damit immer wieder nahezu unbrauchbare Dateien ausgeliefert habe, da der IE z.B. eine CSS Datei mit BOM auch einfach mal so ignorieren kann.

Heute habe ich des Rätsels Lösung gefunden. Eben das besagt BOM. Das Teufelszeug.

BOM = Bytereihenfolge-Markierung und wird dazu verwendet um z.B eine UTF-8 Datei als UTF-8 kodiert zu markieren.
Dies macht beim Datenaustausch sicher sinn, kann aber bei der Web oder C++ Entwicklung sich als sehr hinderlich erweisen. Die UTF-8-Kodierung des BOM besteht aus der Bytesequenz EF BB BF, die in den ISO-8859-1-Zeichen  erscheint.

Ich habe nun in BBEdit UTF-8 ohne BOM eingestellt und werde damit hoffentlich endlich Frieden finden :-)

Geschrieben von Peter Rehm

09.04.2007 um 22:28:42

Abgelegt in Programmierung

Tags für diesen Artikel: , ,

Mails UTF-8 kodiert versenden

Ohne Kommentare

Ergänzend zum dem Eintrag bezüglich UTF-8 in Webapplikationen hier noch eine kurze Info zum versenden von UTF8 Mails mit PHP.

Man kann zum einen die Mails wieder in ISO konvertieren, allerdings möchte ich nur auf die Möglichkeit eingehen,
Mails unkonvertiert zu versenden. Dazu muss an sich nur das Encoding im Header in der Funktion mail()
gesetzt werden.

CODE:
mail("reciever@reciever.de",
 "subject",
 "content",
 "From: bla@bla.de\r\nContent-Type: text/plain; charset=UTF-8");


Alternativ kann man auch mb_send_mail() verwenden.

Geschrieben von Peter Rehm

17.02.2007 um 18:04:50

Abgelegt in PHP

Tags für diesen Artikel: ,

UTF-8 in Webapplikationen

Mit 3 Kommentaren

Um mein CMS auch in bulgarisch betreiben zu können, musste ich mich nun mit UTF-8 beschäftigen.

Die Erfahrungen will ich hier nun kundtun.

Es ist vielleicht noch keine perfekte Lösung, aber Sie tut erstmal Ihren Dienst.

Allgemeines

Zum ersten muss dem Browser gesagt werden, welches Charset verwendet werden soll, nämlich UTF-8.
Dies ist vor allem dann ein Problem wenn der Browser das selbst festlegt, kann man böse Überraschungen
erhalten.

CODE:
<meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8" />


Dies sollte überall eingebunden werden. Man kann auch in der Css festlegen, welche Zeichensatz
verwendet werden soll, dies habe ich bisher aber noch nicht benötigt :-)

CODE:
@charset "utf-8";


Praktisch ist vor allem im Umgang mit PHP, die Anwendung von header()

CODE:
header('content-type: text/html; charset=utf-8');


Man kann dies auch in der php.ini spezifizieren, sofern man Zugriff darauf hat. (default_mimetype & default_charset)

Damit der Besucher der Website auch in allen Formularen UTF-8 eingeben kann sollte man
accept-charset in den FORM-Kopf mit aufnehmen.

CODE:
<form accept-charset="utf-8" method=…


Der Vollständigkeit halber auch noch die Einbindung in XML

CODE:
<?xml version="1.0" encoding="utf-8"?>


PHP

All diese Einstellungen machen es möglich, dass UTF eingegeben und ausgegeben werden kann.
Die meisten die das verwenden haben allerdings eine Datenbank im Hintergrund, und schon da kann
es komplizierter werden. Als erstes benötigen wir eine Funktion, die überprüft ob ein String bereits
UTF-8 ist:

CODE:
/**
* Checks if String is UTF-8 Encoded
* @param string $string string to check
* @return boolean
*/
function is_utf8($string) 
{
return preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $string);
}


Dies ist nach der Vorgabe von W3.
Somit kann nun schoneinmal festgestellt werden ob der String utf8 ist.

Nun noch eine Funktion, die UTF8 encodiert. Achtung, die Funktion benötigt is_utf8()

CODE:
/**
* Encodes String to UTF8
* @param string $string
* @return string
*/
function cms_utf8_encode($string)
{
if(is_utf8($string))
{
return $string;
} else {
if(function_exists('mb_convert_encoding'))
{
return mb_convert_encoding($string,'utf-8');
} else {
return utf8_encode($string);
}
}
}


Hier wird der String encodiert, bevor er z.B. in die Datenbank geschrieben wird.

Datenbank

Ich habe mich auch mit dem Thema UTF-8 und Datenbank auseinandergesetzt. Dabei muss man folgendes Wissen:
UTF-8 kostet mehr als z.B. der latin1 Zeichensatz, da mehr Speicherplatz verwendet wird. Sogar 3x soviel :-)
Daher habe ich mich dazu entschlossen, da in der regel die wenigsten Zeichen in meinem System in Unicode gespeichert werden sollen, den latin1 Zeichensatz zu lassen.

Ich encodiere nur UTF-8 und leg das eben dann so ab. Funktioniert wunderbar, und ich hoffe das gibt keine Probleme.

In dem zug auch eine sehr detaillierte Beschreibung zu dem Thema von Kris Köhntopp.

Geschrieben von Peter Rehm

18.11.2006 um 14:05:13

Tags für diesen Artikel: , , , ,