Kram ► Codeschnipsel ► UTF-8 Kodierung/Dekodierung (C++)
Sie betrachten eine ältere Version der ionflux.org website! Bitte besuchen Sie die neue Version hier.

UTF-8 Kodierung/Dekodierung (C++)

UTF-8 ist eine Zeichenkodierung, die eine unglaubliche Menge an Zeichen (den gesamten Unicode-Zeichensatz) unterstützt und es erlaubt, Texte in nahezu jeder Schrift der Welt zu schreiben und zu übertragen - ohne dabei zu ineffizient zu sein. UTF-8 ist dabei die Standardkodierung auf Computern und in Netzwerken zu werden. Hier [externer Link] bekommen Sie genauere Informationen darüber, was UTF-8 ist und wie es funktioniert. Die Codeschnipsel in dieser Sektion bieten Kodierung/Dekodierung von UTF-8 Zeichenketten und verschiedene Hilfsfunktionen.

Jedes Zeichen im Unicode-Zeichensatz wird durch einen numerischen Wert identifiziert. UTF-8 Zeichenketten sind sind Ketten von Bytes, wobei ein Zeichen durch ein oder mehrere Bytes repräsentiert wird, je nachdem welchen numerischen Wert es hat. Für den Zweck dieses Quellcodes werden dekodierte Unicode-Zeichen als vorzeichenlose Ganzzahlen repräsentiert, während kodierte UTF-8-Zeichen einfach Standard-C++ Zeichenketten sind.

Kodierer für einzelne Zeichen

Der folgende Quellcode konvertiert ein einzelnes Unicode Zeichen zur zugehörigen UTF-8 Zeichenkette. Dies ist vielleicht nicht so schön, aber trotzdem notwendig. ;-)

#include <iostream> #include <string> std::string uint_to_utf8(unsigned int uniChar) { std::string result; if (uniChar < 128U) result.append(1, static_cast<unsigned char>(uniChar)); else if (uniChar < 2048U) { result.append(1, static_cast<unsigned char>((uniChar >> 6) | 0xc0)); result.append(1, static_cast<unsigned char>((uniChar & 0x3f) | 0x80)); } else if (uniChar < 65536U) { result.append(1, static_cast<unsigned char>((uniChar >> 12) | 0xe0)); result.append(1, static_cast<unsigned char>(((uniChar >> 6) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>((uniChar & 0x3f) | 0x80)); } else if (uniChar < 2097152U) { result.append(1, static_cast<unsigned char>((uniChar >> 18) | 0xf0)); result.append(1, static_cast<unsigned char>(((uniChar >> 12) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 6) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>((uniChar & 0x3f) | 0x80)); } else if (uniChar < 67108864U) { result.append(1, static_cast<unsigned char>((uniChar >> 24) | 0xf8)); result.append(1, static_cast<unsigned char>(((uniChar >> 18) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 12) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 6) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>((uniChar & 0x3f) | 0x80)); } else if (uniChar < 2147483648U) { result.append(1, static_cast<unsigned char>((uniChar >> 30) | 0xfc)); result.append(1, static_cast<unsigned char>(((uniChar >> 24) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 18) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 12) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>(((uniChar >> 6) & 0x3f) | 0x80)); result.append(1, static_cast<unsigned char>((uniChar & 0x3f) | 0x80)); } else std::cerr << "[uint_to_utf8] WARNING: Character not representable by UTF-8." << std::endl; return result; }

Dekodierer für einzelne Zeichen

Der folgende Quellcode dekodiert das erste Unicode-Zeichen in einer UTF-8 Zeichenkette.

#include <iostream> #include <string> bool utf8_to_uint(const std::string& bytes, unsigned int& target) { unsigned int size = bytes.size(); target = 0; bool result = true; if (size == 1) { if ((bytes[0] >> 7) != 0) { // ----- WARNING ----- // std::cerr << "[utf8_to_uint] WARNING: Invalid single-byte character." << std::endl; // ----- WARNING ----- */ result = false; } else target = bytes[0]; } else { unsigned char byte = bytes[0]; target = ((byte & (0xff >> (size + 1))) << (6 * (size - 1))); unsigned int i = 1; while (result && (i < size)) { byte = bytes[i]; if ((byte >> 6) != 2) { // ----- WARNING ----- // std::cerr << "[utf8_to_uint] WARNING: Invalid byte (" << static_cast<unsigned int>(byte) << ") in UTF-8 sequence at position " << i << "." << std::endl; // ----- WARNING ----- */ result = false; } else target |= ((byte & 0x3f) << (6 * (size - 1 - i))); i++; } } return result; }

Kodierer für Zeichenketten

Dieser Schnipsel kann verwendet werden, um eine ganze Zeichenkette von Unicode-Zeichen, angegeben als Vektor von numerischen Code-Werten, in eine UTF-8 Zeichenkette umzuwandeln. Dabei ist eigentlich nichts Besonderes - der Code ruft einfach die Version von uint_to_utf8() für einzelne Zeichen mehrmals auf.

#include <string> #include <vector> void uint_to_utf8(const std::vector<unsigned int>& uniChars, std::string& target) { target = ""; for (unsigned int i = 0; i < uniChars.size(); i++) target.append(uint_to_utf8(uniChars[i])); }

Dekodierer für Zeichenketten

Hier ist nun der Dekodierer für UTF-8 Zeichenketten, der eine Standard-Zeichenkette von der UTF-8 Kodierung in einen Vektor von numerischen Unicode-Werten umwandelt. Diese Funktion benötigt noch weiteren Quellcode, der die Länge eines UTF-8 Zeichens berechnet. Dies ist notwendig, da ein Zeichen mehr als ein Byte benötigen kann, um in der UTF-8 Kodierung dargestellt werden zu können.

#include <string> #include <vector> unsigned int utf8_get_size(unsigned char byte) { if (byte < 128) return 1; else if ((byte & 0xe0) == 0xc0) return 2; else if ((byte & 0xf0) == 0xe0) return 3; else if ((byte & 0xf8) == 0xf0) return 4; else if ((byte & 0xfc) == 0xf8) return 5; else if ((byte & 0xfe) == 0xfc) return 6; // ----- WARNING ----- // std::cerr << "[utf8_get_size] WARNING: Invalid character size." << std::endl; // ----- WARNING ----- */ return 0; } bool utf8_to_uint(const std::string& bytes, std::vector<unsigned int>& target) { unsigned int size = bytes.size(); unsigned int i = 0; unsigned int charSize = 0; unsigned int currentChar = 0; bool result = true; target.clear(); while (result && (i < size)) { charSize = utf8_get_size(bytes[i]); if ((charSize > 0) && ((i + charSize) <= size) && utf8_to_uint(bytes.substr(i, charSize), currentChar)) i += charSize; else { // ----- WARNING ----- // std::cerr << "[utf8_to_uint] WARNING: Could not convert UTF-8 character " "(size = " << charSize << ", position = " << i << ")." << std::endl; // ----- WARNING ----- */ result = false; } if (result) target.push_back(currentChar); } return result; }

Länge einer UTF-8 Zeichenkette

Es mag Fälle geben, in denen es wünschenswert ist, die Länge einer UTF-8 Zeichenkette in Zeichen (nicht Bytes) zu kennen. Dies ist leider nicht möglich, ohne die gesamte Zeichenkette zu lesen - außer man berechnet die Länge beim Erstellen der Zeichenkette und speichert sie dann zusammen mit den kodierten Daten - aber das wäre geschummelt. Hier ist also eine Funktion, die die Länge der UTF-8 Zeichenkette berechnet, ohne sie tatsächlich zu dekodieren.

#include <string> unsigned int utf8_get_size(const std::string& bytes) { unsigned int size = bytes.size(); unsigned int i = 0; unsigned int charLen = 0; unsigned int result = 0; bool error = false; while (!error && (i < size)) { charLen = utf8_get_size(bytes[i]); if (charLen > 0) { result++; i += charLen; } else error = true; } if (error) return 0; return result; }
© 2006-2007 Jörn P. Meier  •  Impressum  •  Datenschutz  •  Kontakt: webmaster@ionflux.org  •  Letzte Aktualisierung: 2009-04-27  •  Version 2.0  •  Sprache: en | de