Jonny 5: BOM \X\0\X\0 - Frage zu Zeichensätzen

Hallo liebes Forum,

auf manchen Internetseiten stoße ich auf seltsame Zeichensequenzen.

Nach jedem zweiten Zeichen tritt das ASCII-Zeichen 0 (String-Ende) auf.

Beispiele:
www.wienproducts.at
www.gbvienna.com

Interessant:
http://www.google.at/search?hl=de&q=www.wienproducts.at
http://www.google.at/search?hl=de&q=www.gbvienna.com

Kann mir jemand erklären, was es damit auf sich hat?

herzliche Grüße,
Jonny 5

  1. Yerf!

    Nach jedem zweiten Zeichen tritt das ASCII-Zeichen 0 (String-Ende) auf.

    Kann mir jemand erklären, was es damit auf sich hat?

    Das ist UTF-16, eine 16-bit Kodierung für Unicode. Dabei wird jedes Zeichen mittels 2 Bytes dargestellt. Bei den Zeichen die auch in ASCII vorkommen ist dabei das höherwertige Byte immer 0 (Bei Sonderzeichen kann da dann schon mal etwas anderes stehen). Deshalb gibt es auch die UTF-8 Kodierung, die solche Zeichen nur mit einem Byte darstellt, aber trotzdem alle Unicode-Zeichen darstellen kann (etwas das UTF16 glaub ich nicht kann, da es inzwischen über 65536 Zeichen in Unicode gibt).

    Weitere Erläuterungen kannst du z.B. in Wikipedia finden.

    Gruß,

    Harlequin

    1. Hall nochmal,

      Das ist UTF-16, ...

      danke für die rasche Antwort.

    2. Hallo Harlequin,

      Als Ergänzung:

      [UTF-16] Bei den Zeichen die auch in ASCII vorkommen ist dabei das höherwertige Byte immer 0 (Bei Sonderzeichen kann da dann schon mal etwas anderes stehen). Deshalb gibt es auch die UTF-8 Kodierung, die solche Zeichen nur mit einem Byte darstellt, aber trotzdem alle Unicode-Zeichen darstellen kann

      ... wobei UTF-8 für Nicht-ASCII-Zeichen mindestens 2 Bytes benötigt, manchmal noch mehr und nur ASCII-Zeichen mit 1 Byte auskommen (nur als Klarstellung).

      (etwas das UTF16 glaub ich nicht kann, da es inzwischen über 65536 Zeichen in Unicode gibt).

      Nein, UTF-16 kann den gesamten Unicode-Bereich abdecken. Zeichen, die nicht mehr zum BMP gehören werden (die BMP ist etwas weniger als die vollen 16bit groß) in UTF-16 durch 2 sogenannte "Surrogates" dargestellt, d.h. durch zwei Hilfszeichen hintereinander. Damit ist UTF-16 keine 16-bit-Kodierung im Sinne "jedes Zeichen ist 16 bit lang", sondern nur eine 16-bit-Kodierung im Sinne "die Basiseinheit der Kodierung ist 16 bit, alle Zeichen werden als ganzzahlige Vielfache davon dargestellt". In UTF-16 können Zeichen entweder 2 oder 4 Oktetts groß sein.

      Viele Grüße,
      Christian

  2. echo $begrüßung;

    Nach jedem zweiten Zeichen tritt das ASCII-Zeichen 0 (String-Ende) auf.

    Ein 0-Byte steht vielleicht in C für ein String-Ende, hat aber in ASCII oder anderen Zeichenkodierungen diese Bedeutung nicht.

    Beispiele:
    www.wienproducts.at
    www.gbvienna.com

    Interessant:
    http://www.google.at/search?hl=de&q=www.wienproducts.at
    http://www.google.at/search?hl=de&q=www.gbvienna.com

    Kann mir jemand erklären, was es damit auf sich hat?

    Beide Beispiele sind fehlerhaft. Die Zeichenkodierung wird durch eine ergänzende Angabe (charset=...) im HTTP-Header "Content-Type" angegeben. Fehlt diese, kann ein gleichnamiges Meta-Element herangezogen werden. Beide Seiten haben keine Angabe im HTTP-Header. Das erste Beispiel hat ein Meta-Element, das aber fälschlicherweise UTF-8 angibt. Das zweite verzichtet auf dieses Element. Beide Dokumente beginnen aber mit einer so genannten Byte-Order-Markierung (BOM), und aus der errät der Firefox die zu verwendende Kodierung (Rechtsklick -> Seiteninformation anzeigen). Google hingegen scheint an dem Ratespiel keine Lust zu haben. Vermutlich deswegen kommt es dort zu den von dir beobachten Lücken zwischen den einzelnen Zeichen und der Anzeige der HTML-Elemente.

    echo "$verabschiedung $name";

    1. Hallo,

      Google hingegen scheint an dem Ratespiel keine Lust zu haben.

      Bei einem eindeutigen UTF-16LE-BOM gibts eigentlich nix zu raten. Ich würd das eher als Dummheit von Google bezeichnen, schließlich muss und kann Google bei Millionen anderen Dokumenten ebenfalls die Kodierung raten, ohne dass die Kodierungsangaben enthalten. Da ist dieser Fall noch der einfachste.

      Mathias

  3. Vielen Dank nochmal für alle Antworten!

    So konnte ich eine kleine Funktion zur Erkennung des BOM schreiben.

    Man speist sie mit den ersten Bytes einer Datei und Sie sollte, falls ein Byte Order Mark erkannt wird, das entsprechende Encoding/Charset für die php-mb-string Konvertierung liefern. Natürlich verbesser- und erweiterbar.

    Vielleicht benötigt Sie mal jemand, also poste ich sie gleich mit:

      
      
    # detect bom and match charset  
    # ----------------------------  
    # $first_bytes: 4 leading bytes of file  
    # $boms: valid byte order marks  
    function detectBOM($first_bytes=NULL){  
      if($first_bytes!==NULL){  
        # valid byte order marks  
        $boms=array('UTF-8' =>    '\xEF\xBB\xBF',     # utf-8  
                    'UTF-32BE' => '\x00\x00\xFE\xFF', # utf-32 big endian  
                    'UTF-32LE' => '\xFF\xFE\x00\x00', # utf-32 little endian  
                    'UTF-16BE' => '\xFE\xFF',         # utf-16 big endian  
                    'UTF-16LE' => '\xFF\xFE');        # utf-16 little endian  
        # cylcle through boms -> return charset  
        foreach($boms AS $charset => $bom){  
          if(preg_match('~^'.$bom.'~',$first_bytes)){  
            return $charset;  
          }  
        }  
      }  
      return false;  
    }  
      
    
    

    herzliche Grüße,
    Jonny 5