efinf:blc2016:bitsundbytes:utf8

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
efinf:blc2016:bitsundbytes:utf8 [2016/09/14 18:23] – [WTF?] Ivo Blöchligerefinf:blc2016:bitsundbytes:utf8 [2016/09/15 13:21] (current) – [Kodierung und Dekodierung von Unicode nach und von UTF-8] Ivo Blöchliger
Line 1: Line 1:
 +===== Kodierung von Buchstaben und Symbolen =====
 +==== ASCII ====
 +* 7 Bit, keine Akzente, kaum Sonderzeichen.
 +
 +https://en.wikipedia.org/wiki/ASCII
 +
 +==== Latin1 aka. ISO-8859-1 und Windows-1252 ====
 +* 8 Bit, deckt viele Sonderzeichen Westeuropas ab. Windows-1252 (auch CP-1252) ist eine Erweiterung von Latin1 und nutzt dort undefinierte Zeichen (z.B. das € Zeichen). In unserer Region nach UTF8 wohl die verbreitetste Kodierung.
 +
 +https://en.wikipedia.org/wiki/Windows-1252
 +
 +==== Unicode ====
 +Idee: Jedem Symbol seine eigene Nummer. Plus Möglichkeiten zum Setzen von Akzenten, Festlegen und Ändern der Schreibrichtung etc.
 +
 +Zum Kodieren dieser Nummern gibt es verschiedene Systeme. Das am weitesten verbreitete System ist UTF-8.
 +
 +**Klarstellung** Unicode ist noch Kodierung in Bits und Bytes, sondern nur eine Nummerierung der Symbole (bzw. Kodierung als natürliche Zahl). Wie dann diese Zahl effektiv mit Bits und Bytes kodiert wird, dafür gibt mehrere gebräuchliche Varianten.
 +
 +https://en.wikipedia.org/wiki/Unicode
 +
 +=== UTF-8 ===
 +UTF-8 ist die am häufigsten verwendete Kodierung (im Sinne von "Umsetzung in Bits und Bytes") für Unicode. Es ist ein faszinierend durchdachtes Format. Siehe z.B. https://en.wikipedia.org/wiki/UTF-8#Advantages_and_disadvantages
 +
 +==== Kodierung und Dekodierung von Unicode nach und von UTF-8 ====
 +
 +Referenz:
 +
 +https://en.wikipedia.org/wiki/UTF-8#Description
 +
 +<code ruby utf8.rb>
 +# Die untersten 6 Bit mit
 +# höchstem Bit gesetzt als string
 +def folgebyte(byte)
 +    ((byte & 0b11_1111) | 0b1000_0000).chr
 +end
 +
 +# Eingabe: Zahl (Unicode des Symbols)
 +# Ausgabe: String mit diesem Zeichen
 +def to_utf8(unicode)
 +  utf8=""     # Leerer String
 +  # String aufbauen
 +  if (unicode<0x80)  # pure ASCII
 +      utf8 = unicode.chr
 +  elsif unicode<0x800
 +      byte1 = ((unicode >> 6) & 0b1_1111) | 0b1100_0000
 +      utf8 = byte1.chr + folgebyte(unicode)
 +  elsif unicode < 0x10000
 +      byte1 = ((unicode >> 12) & 0b1_1111) | 0b1110_0000
 +      utf8 = byte1.chr + folgebyte(unicode >> 6) + folgebyte(unicode) 
 +  else
 +      byte1 = ((unicode >> 18) & 0b1_1111) | 0b1111_0000
 +      utf8 = byte1.chr + folgebyte(unicode >> 12) + folgebyte(unicode >> 6) + folgebyte(unicode) 
 +  end
 +  # Dem String sagen er sei UTF-8 kodiert (sonst ASCII-8Bit)
 +  utf8.force_encoding(Encoding::UTF_8)
 +end
 + 
 +# Eingabe: String mit einem Unicode-Zeichen
 +# Ausgabe: Zahl (entsprechende Unicode-Nummer)
 +def to_unicode(utf8)
 +   b = utf8.bytes    # Ein Array mit entsprechenden Bytes
 +   # Resultat der Funktion: Resultat des letzten Ausdrucks.
 +   # In diesem Fall das Resultat des case-statements.
 +   # Resultat von case: 
 +   # Letztes Resultat des entsprechenden
 +   # when.
 +   case b.size  # Anzahl Einträge
 +   when 1
 +       b[0]
 +   when 2
 +       (b[1] & 0b11_1111) | 
 +       ((b[0] & 0b1_1111) << 6)
 +   when 3
 +       (b[2] & 0b11_1111) | 
 +       ((b[1] & 0b11_1111) << 6) | 
 +       ((b[0] & 0b1111) << 12)       
 +   when 4
 +       (b[3] & 0b11_1111) | 
 +       ((b[2] & 0b11_1111) << 6) | 
 +       ((b[1] & 0b11_1111) << 12) | 
 +       ((b[0] & 0b111) << 18)
 +   end 
 +end
 + 
 +# Einige Tests:
 +"Aö♣♥✓✌计算机科学𝅘𝅥𝅮".each_char{|c|
 +  puts "Code von #{c} ist #{to_unicode(c)}  sollte sein: #{c.ord} = 0x#{c.ord.to_s(16)}"
 +}
 + 
 +[0x261E, 0x2744, 0x1D120, 0x1D160, 0x24, 0xA5, 0x20AC].each{|u|
 +  puts "Unicode 0x#{u.to_s(16)}=#{u} : #{to_utf8(u)}   und zurück: #{to_unicode(to_utf8(u))}"
 +}
 +</code>
 +
 +===== WTF? =====
 +Der folgende Ruby-Code gibt 42 aus (wenn man diesen kopiert und nicht abschreibt)
 +<code ruby wtf-utf8.rb>
 +o = -1
 +о = 7
 +ο = о+o
 +puts (ο-o)*ο
 +</code>