6 Stimmen

Effiziente Binär-zu-Zeichenfolge-Formatierung (wie base64, aber für UTF8/UTF16)?

Ich habe viele Pakete mit Binärdaten zwischen 16 und 4096 Bytes, die in einer Datenbank gespeichert werden müssen und die als Einheit leicht vergleichbar sein sollten (z. B. zwei Pakete mit Daten, die nur dann zusammenpassen, wenn die Längen und alle Bytes übereinstimmen). Strings sind dafür gut geeignet, aber die blinde Konvertierung von Binärdaten in einen String kann aufgrund von Problemen bei der Zeichenkodierung/Uminterpretation zu Problemen führen.

Base64 war eine gängige Methode zum Speichern von Zeichenketten in einer Zeit, in der 7-Bit-ASCII die Norm war; die 33%ige Leerraumeinbuße war zwar etwas ärgerlich, aber nicht schrecklich. Wenn man UTF-16 verwendet, beträgt der Platzverlust leider 166 % (8 Byte für 3 Byte), was ziemlich eklig ist.

Gibt es eine gängige Speichermethode zum Speichern von Binärdaten in einer gültigen Unicode-Zeichenkette, die eine bessere Effizienz in UTF-16 ermöglicht (und hoffentlich nicht zu schrecklich in UTF-8 ist)? Eine Base-32768-Kodierung würde 240 Bits in sechzehn Zeichen speichern, was 32 Bytes von UTF-16 oder 48 Bytes von UTF-8 erfordern würde. Im Vergleich dazu würde die base64-Kodierung 40 Zeichen verwenden, was 80 Byte UTF-16 oder 40 Byte UTF-8 erfordern würde. Ein Ansatz, der so konzipiert wurde, dass er in UTF-8 oder UTF-16 den gleichen Platz einnimmt, könnte 48 Bits in drei Zeichen speichern, die in UTF-8 oder UTF-16 acht Bytes beanspruchen würden, so dass 240 Bits in 40 Bytes von UTF-8 oder UTF-16 gespeichert würden.

Gibt es für so etwas irgendwelche Normen?

8voto

qntm Punkte 3787

Basis32768 macht genau das, was Sie wollten. Es tut mir leid, dass es fünf Jahre gedauert hat, bis es existierte.

Verwendung (dies ist JavaScript, obwohl die Portierung der base32768 Modul in eine andere Programmiersprache zu übertragen, ist äußerst praktisch):

var base32768 = require("base32768");

var buf = new Buffer("d41d8cd98f00b204e9800998ecf842", "hex"); // 15 bytes

var str = base32768.encode(buf); 
console.log(str); // "", 8 code points

var buf2 = base32768.decode(str);
console.log(buf.equals(buf2)); // true

Base32768 wählt 32.768 Zeichen aus der Basic Multilingual Plane aus. Jedes Zeichen benötigt 2 Byte, wenn es als UTF-16 dargestellt wird, bzw. 3 Byte, wenn es als UTF-8 dargestellt wird, was genau die von Ihnen beschriebenen Effizienzmerkmale ergibt: 240 Bits können in 16 Zeichen gespeichert werden, d. h. 32 Byte UTF-16 oder 48 Byte UTF-8. (Abgesehen von dem gelegentlichen Auffüllzeichen, analog zum = Padding in Base64).

Dazu werden die Eingabebytes (d.h. 8-Bit-Zahlen ohne Vorzeichen) in 15-Bit-Zahlen ohne Vorzeichen zerlegt und jede daraus resultierende 15-Bit-Zahl einem der 32.768 Zeichen zugeordnet.

Beachten Sie, dass die ausgewählten Zeichen auch "sicher" sind - keine Leerzeichen, Steuerzeichen, kombinierte diakritische Zeichen oder Anfälligkeit für Normalisierungsfehler.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X