Interne Zeichenkodierung, Characters, Bytes und Bytesemantics

Eine Zeichenkodierung wird nur innerhalb eines Programmes benötigt

Seit Perl v5.6 intern zwischen Zeichenketten (Characters) und Bytes (Oktetten) unterscheidet, gibt es eine Reihe an Missverständnissen die nicht abreißt. Dabei ist doch die Sache auch in anderen Programmen schon immer so gewesen, daß die Zeichenkodierung nur innerhalb des Programms eine Rolle spielt, nicht jedoch außerhalb auf der Ebene der Massenpeicher. Nehmen wir doch mal unser allseits geliebtes Briefeschreibprogramm namens Word und schreiben einen schönen Bief, vielleicht sogar eine Rechnung wo das Eurozeichen drin vorkommt. Mit Sicherheit kommen da noch ungezählte Umlaute hinzu. Wenn wir sehen wie Word das Wort Hunde­übungsplatz fein säuberlich trennen kann, wird uns klar: Hier spielen Zeichen die Hauptrolle! Denn Word kann ganz genau zwischen den Zeichen e und ü dieses zusammengesetzte Word trennen, sofern es nicht mehr auf eine Zeile passt.

Der Browser kann das übrigens auch, wenn Sie das Bild seitlich zusammenschieben, sehen Sie das. Doch bleiben wir bei unserem Briefchen was wir nun unter dem Namen hundeübungsplatz_rechnung.doc zu speichern gedenken. Beim Erstenmal Speichern fragt uns Word nach der Zeichenkodierung, wir wählen UTF-8 und machen uns im Folgenden ein paar Gedanken darüber, wie dieser Brief samt Dateinamen auf der Festplatte abgelegt wird.

Gespeichert werden nicht Zeichen sondern Bytes

Zum Speichern also, wird die interne Kodierung abgeschaltet. Nicht nur weil sie nur intern im Programm gebraucht wurde, sie wird hauptsächlich deswegen abgeschaltet, weil das Betriebssystem da draußen gar nicht wissen kann, wie Word intern mit der Kodierung umgeht. Demzufolge bekommt das Betriebssystem keine Zeichen zum Speichern sondern Rohdaten in Form von Bytes.

Das Byte ist die kleinste Speichereinheit auf jeder Maschine und auf den unterschiedlichsten Betriebssystemen. Das haben wir bestimmt schon einmal irgendwo gehört oder gelesen und wissen vielleicht auch, daß ein Byte aus 8 Bit besteht. Was jedoch für die meisten von uns neu sein dürfte: Ein Byte speichert gar nicht ein Zeichen sondern nur eine Zahl! Wobei diese Zahl eine ganze Zahl ist und einen Wert zwischen 0 und 255 annnehmen kann, die sogenannte Oktettenwertigkeit.

Wenn wir nun unseren Brief am nächsten Tag wieder öffnen mit Word, öffnen wir eine Datei die nur Zahlen gespeichert hat, warum jedoch sehen wird dann unsere Zeichen samt der Rechnung wieder? Die Antwort ist ganz einfach: Word stellt die beim letzten Speichern gewählte interne Zeichenkodierung wieder her!

Und genauso wie Word das macht, können und müssen wir das in unseren Perl-Programmen machen.

SvUTF8 - Scalar Value UTF8

Betrachte das Grundanliegen von Encode.pm was seit v5.8 ein Core Modul ist:

use Encode qw(decode encode);
$characters = decode('UTF-8', $octets,     Encode::FB_CROAK);
$octets     = encode('UTF-8', $characters, Encode::FB_CROAK);

# oder auch
$characters = decode_utf8($octets);
$octets     = encode_utf8($characters);

Diese beiden Funktionen vermitteln also zwischen der internen Zeichenkodierung ($characters) und den Bytes ($octets) die nach draußen gehen oder von draußen reinkommen. Merke: Gib niemals $characters nach draußen sondern stets díe Oktetten! Andernfalls führt das unweigerlich zu Zeichensalat. Und: Nach draußen heißt STDOUT, FILEHANDLE, Socket und auch Dateinamen fallen darunter.

Charactersemantic in Perl

Betrachte untenstehenden Code:

use strict;
use warnings;
use Encode;

# intern kodierte Zeichenkette
my $chars = decode_utf8('äöü');

# zur Großschreibung umwandeln
$chars = uc $chars;

# Kodierung zur Ausgabe abschalten
print encode_utf8 $chars;

# oder so
use bytes;
print $chars;

Wie wir hier schon sehen, es gibt mehrere Möglichkeiten. Der Grundsatz ist jedoch immer derselbe der beachtet und umgesetzt werden muss: Wenn eine intern kodierte Zeichenkette an das OS (Betriebssystem) oder FS (Dateisystem) abzugeben ist, muss dazu die interne Kodierung abgeschaltet sein!

Bytesemantic in Perl

Wie wir oben schon gesehen haben: use bytes; schaltet für alle nachfolgenden Zeilen die Charactersemantic ab und dafür die Bytesemantic ein. Die Umkehrung, no bytes; schaltet wieder um zur Charactersemantic. Natürlich können wir dasselbe auch über die weiter oben vorgestellten Fúnktionen erreichen, wie gesagt, es gib mehrere Möglichkeiten.

Wichtig jedoch ist hierzu Folgender Sachverhalt: Sämtliche Stringfunktionen wie length(), uc(), lc(), substr() und split() arbeiten entweder bytesemantisch oder charactersemantisch! Wobei die Funktionen uc() und lc() mit Oktetten gar nicht können sondern ausschließlich nur mit kodierten Zeichenketten.

Bytesemantisch wird substr('äöü', 0, 1) eben nicht das Zeichen ü liefern sondern nur das erste Byte von diesem Zeichen, was utf-8-kodiert aus 2 Bytes besteht.

UTF-8 im Perlscript selbst

Kein Problem, speichern Sie das Script einfach als utf-8-kodiert ab. So werden für ein print "2,50 €" die richtigen Oktetten gespeichert und auch auf STDOUT ausgegeben. Merke: Die interne Kodierung wird nur gebraucht, wenn intern mit Zeichenketten operiert werden muss! Wenn jedoch nur Literale auf print() auszugeben sind, wird die interne Kodierung nicht benötigt, da ist es unsinnig eine Solche ein~ und wieder auszuschalten!

Zeichenkodierung ist Mathematik

Spätestens hier dürfte das jedem klar sein. Während der Codpoint eines Zeichen zum Einen der Verwaltung im UNICODE System dient, werden auch die diesbezüglichen Oktetten aus dem Codepoint berechnet. So läßt sich aus dem Codepoint ganz exakt berechnen, welche Bytes sich daraus für eine UTF-8-Kodierung ergeben. Die Umkehrung ist ein bischen komplizierter:

Aber so kompliziert ist das nun auch wieder nicht.


Die rein persönlichen Zwecken dienende Seite verwendet funktionsbedingt einen Session-Cookie. Datenschutzerklärung: Auf den für diese Domäne installierten Seiten werden grundsätzlich keine personenbezogenen Daten erhoben. Das Loggen der Zugriffe mit Ihrer Remote Adresse erfolgt beim Provider soweit das technisch erforderlich ist. @: nmq​rstx-18­@yahoo.de