UNICODE und der ganze Quark

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
7x7
Beiträge: 591
Registriert: 14.08.2007 15:41
Computerausstattung: ganz toll
Wohnort: Lelbach

UNICODE und der ganze Quark

Beitrag von 7x7 »

Das Problem:
Ich möchte Daten aus dem Netzwerk (verschiedene Quellen -> Dateien, Direktübertragungen, Ausgaben aus verschiedenen Anwendungen usw.) verarbeiten. Leider habe ich zu diesen Daten zum Zeitpunkt der Ausgabe/Übertragung keine Ahnung, in welchem Format diese vorliegen (ASCII, UTF-8, UTF-16, UNICODE, UCS2(?) und weiss der Teufel, was es da noch alles gibt).

Beim beschäftigen mit dieser Materie komme ich immer tiefer in Details, die mich letztendlich gar nicht interessieren, die mich nur belasten und mich vom eigentlichen Problem nur aufhalten.


Meine Frage:
Gibt es eine ganz einfache, simple Methode, das Datenformat festzustellen? (...oder diese gleich in einem bestimmten Format zu erhalten?)
- alles was ich hier im Forum sage/schreibe ist lediglich meine Meinung und keine Tatsachenbehauptung
- unkommentierter Quellcode = unqualifizierter Müll
Benutzeravatar
shadow
Beiträge: 189
Registriert: 23.03.2005 17:52
Wohnort: Lübeck

Re: UNICODE und der ganze Quark

Beitrag von shadow »

Laut deinen Ausführungen vermute ich, du meinst ausschließlich Dokumente und deren Zeichensatz-Kodierung.
Schau mal hier:
http://de.wikipedia.org/wiki/Byte_Order_Mark
Alles, was keinen BOM-Header hat, würde ich als ASCII verarbeiten, da man sonst nur durch spezielle Analysen an die verwendete Codepage kommt.
ThinkPad T61 (in Gedenken) | PureBasic 4.61 B1 (32) | Windows 7 (32SP1) | ArchLinux (32) | Syllable (32)
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Re: UNICODE und der ganze Quark

Beitrag von PMV »

Wenn du mit Daten aus dem Netz "HTTP" meinst, dann
gäbs auch die Möglichkeit den entsprechenden content-
type header aus zu lesen, sofern er vom Server gesendet
wurde.

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
Kukulkan
Beiträge: 1066
Registriert: 09.09.2004 07:07
Wohnort: Süddeutschland
Kontaktdaten:

Re: UNICODE und der ganze Quark

Beitrag von Kukulkan »

Hallo,

ich hatte mal eine ähnliche Anforderung. Hier der Code mit dem ich es gelöst habe. Evtl. hilft es dir?

Code: Alles auswählen

; Try's to gather the characterset of the text in the given memory area.
; If you set ByteLength.i = 0, it assumes a null terminated string.
; Possible return-codes:
; "utf-16LE-bom" -> contains utf-16LE encoded text including a bom
; "utf-16BE-bom" -> contains utf-16BE encoded text including a bom
; "utf-8bom" -> contains utf-8 encoded text including a bom
; "utf-8" -> contains utf-8 encoded text
; "ascii" -> only 7 bit chars
; "iso"   -> contains chars > 7 bit, but not utf-8
Procedure.s GetCharactersetMemory(MemPointer.i, ByteLength.i = 0)

  If PeekA(MemPointer.i + 0) = 239 And PeekA(MemPointer.i + 1) = 187 And PeekA(MemPointer.i + 2) = 191
    ; correct UTF8 BOM
    ProcedureReturn "utf-8bom"
  EndIf
  If PeekA(MemPointer.i + 0) = $FF And PeekA(MemPointer.i + 1) = $FE
    ; correct UTF16LE BOM
    ProcedureReturn "utf-16LE-bom"
  EndIf
  If PeekA(MemPointer.i + 0) = $FE And PeekA(MemPointer.i + 1) = $FF
    ; correct UTF16LE BOM
    ProcedureReturn "utf-16BE-bom"
  EndIf
  
  Protected Code.a = 0, AddBytes.i = 0
  Protected x = 0, a = 0
  Protected ValidUTF8 = #True ; init (to negotiate)
  Protected IsASC = #True     ; init (to negotiate)
  
  Repeat
    Code = PeekA(MemPointer.i + x)
    If Code > 127 And ValidUTF8 = #True
      IsASC = #False
      ; This may be the beginning of a UTF8 char
      If     Code & %11100000 = %11000000 ; 1 additional byte
        AddBytes = 1
      ElseIf Code & %11110000 = %11100000 ; 2 additional byte
        AddBytes = 2
      ElseIf Code & %11111000 = %11110000 ; 3 additional byte
        AddBytes = 3
      ElseIf Code & %11111100 = %11111000 ; 4 additional byte
        AddBytes = 4
      ElseIf Code & %11111110 = %11111100 ; 5 additional byte
        AddBytes = 5
      Else
        ValidUTF8 = #False
        Break ; no utf8, because it does not fit the standard
      EndIf
      ; validate utf8 characters
      For a = 1 To AddBytes
        x = x + 1
        Code = PeekA(MemPointer.i + x)
        If Code & %11000000 <> %10000000
          ValidUTF8 = #False
          Break; no utf8, because following bytes do not match "10xxxxxx"
        EndIf
      Next
    EndIf
    x = x + 1
  Until (x >= ByteLength.i And ByteLength.i > 0) Or Code = 0
  
  If ValidUTF8 = #True
    ; found a utf8 start byte followed by at least one following byte (needed for valid utf8)
    ProcedureReturn "utf-8"
  EndIf
  
  If IsASC = #True
    ProcedureReturn "ascii"
  EndIf
  
  ProcedureReturn "iso"

EndProcedure

; Peeking strings from pointers that point to single-byte strings in memory
; It detects the encoding and ensures that it is correctly returned as multibyte or singlebyte.
; Works with unicode memory areas.
Procedure.s PeekSSmart(Memory.i, Length.i)
  Protected CharSet.s = GetCharactersetMemory(Memory.i, Length.i)
  Select CharSet.s
    Case "utf-16LE-bom"
      ProcedureReturn PeekS(Memory.i+2, (Length.i-2)/2, #PB_UTF16) ; peek as UTF16LE ignoring BOM
    Case "utf-16BE-bom"
      ProcedureReturn PeekS(Memory.i+2, (Length.i-2)/2, #PB_UTF16BE) ; peek as UTF16BE ignoring BOM
    Case "utf-8bom"
      ProcedureReturn PeekS(Memory.i+3, Length.i-3, #PB_UTF8) ; peek as utf8 ignoring BOM
    Case "utf-8"
      ProcedureReturn PeekS(Memory.i, Length.i, #PB_UTF8) ; peek as utf8
    Case "iso"
      ProcedureReturn PeekS(Memory.i, Length.i, #PB_Ascii) ; peek as single byte
    Case "ascii"
      ProcedureReturn PeekS(Memory.i, Length.i, #PB_Ascii) ; peek as single byte
  EndSelect
EndProcedure
Mit PeekSSmart() kann man einen Peek machen und bekommt es dann passend (egal ob man unicode oder single byte compiliert). Allerdings kennt es bei weitem nicht alles aber es hilt schonmal. Es erkennt UTF8 auch wenn es keinen BOM gibt und erkennt auch, ob es ASCII ist (alle Zeichen < 127).

Achtung, die UTF-16 Peeks in PeekSSmart() hab ich nie wirklich getestet. Da könnte evtl. noch was falsch sein.

Grüße,

Kukulkan
Antworten