efinf:blc2016:bitsundbytes:utf8

* 7 Bit, keine Akzente, kaum Sonderzeichen.

https://en.wikipedia.org/wiki/ASCII

* 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

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

Referenz:

https://en.wikipedia.org/wiki/UTF-8#Description

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))}"
}

Der folgende Ruby-Code gibt 42 aus (wenn man diesen kopiert und nicht abschreibt)

wtf-utf8.rb
o = -1
о = 7
ο = о+o
puts (ο-o)*ο
  • efinf/blc2016/bitsundbytes/utf8.txt
  • Last modified: 2016/09/15 15:21
  • by Ivo Blöchliger