"OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierungen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
mk-soft
Beiträge: 3871
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von mk-soft »

Wenn ich Textdateien als IncludeBinary verwende Wandel ich diese erst in Unicode um...!

Code: Alles auswählen

file.s = OpenFileRequester("Open ASCII File", "", "File|*.pbi",1, #PB_Requester_MultiSelection)

While file.s

  part.s = GetExtensionPart(file)
  
  file2.s = ReplaceString(file, part, "unicode", #PB_String_NoCase)
  If CreateFile(2, file2)
    If ReadFile(1, file)
      ft = ReadStringFormat(1)
      While Not Eof(1)
        temp.s = ReadString(1, ft)
        WriteStringN(2, temp, #PB_Unicode)
      Wend
    EndIf
    Debug ("File created " + file2)
  EndIf
  file = NextSelectedFileName()
Wend
Hilfsprogramm für mein EventDesigner
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Sicro
Beiträge: 968
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von Sicro »

mk-soft hat geschrieben:Wenn ich Textdateien als IncludeBinary verwende Wandel ich diese erst in Unicode um...!
Ja, ist gut. Bei externen Dateien hat man ja die freie Wahl, im Gegensatz zu internen Strings ("Ein String"). Bei der Entscheidung, welche Codierung zwischen UTF-8 und UNICODE verwendet werden soll, muss überlegt werden, ob Geschwindigkeit (Unicode; Zeichen sind immer 2 Bytes, daher schnell verarbeitbar) oder Datengröße (UTF-8; Zeichen sind zwischen 1 und 4 Bytes, daher langsam verarbeitbar) wichtiger ist.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von ts-soft »

Bei XML handelt es sich ja um StringBearbeitung im weitesten Sinne, da sollte das vorherige Umwandeln
keine Rolle mehr spielen und ist vernachlässigbar. Da würde ich eher beim Standard bleiben und UTF-8 nutzen,
weil andere Formate wären komisch. HTML usw. wird ja auch in UTF-8 gespeichert.

Wer aber unbedingt ein paar ms sparen will, bitte :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Sicro
Beiträge: 968
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von Sicro »

Ja, im Normalfall sollte man beim Standard bleiben und XMLs in UTF-8 speichern.
Beim Inkludieren einer XML-Datei würde ich vom Standard aber abweichen, weil nach dem Kompilieren wieso keiner mehr Zugriff auf den XML-Code hat und das Auslesen ohne Umwege durchgeführt werden kann:

Code: Alles auswählen

CatchXML(0, ?StartXMLFile, ?EndXMLFile - ?StartXMLFile)

DataSection
  StartXMLFile:
  IncludeBinary "XML.xml" ; Datei ist im Unicode-Format
  EndXMLFile:
EndDataSection
Anstatt so:

Code: Alles auswählen

; Da CatchXML erwartet das der XML-Code in Unicode vorliegt, müssen wir vorher noch von UTF-8 in Unicode umwandeln.
Define XML$ = PeekS(?StartXMLFile, ?EndXMLFile - ?StartXMLFile, #PB_UTF8)

CatchXML(0, @XML$)

DataSection
  StartXMLFile:
  IncludeBinary "XML.xml" ; Datei ist im UTF-8-Format
  EndXMLFile:
EndDataSection
Wenn sie anstatt zu Inkludieren per LoadXML() geladen wird, würde ich beim Standard bleiben und sie in UTF-8 beilegen. Hier geht es ohne Umwege, weil LoadXML() im Gegensatz zu CatchXML() den XML-Code in UTF-8 erwartet.
Edit: Hier bin ich durcheinander gekommen. Natürlich liest CatchXML() standardmäßig UTF-8, daher funktioniert es mit einer UTF-8-XML-Datei ohne Umwege.

Hier noch ein Code der veranschaulicht wie CatchXML() funktioniert, um alle Unklarheiten auszuräumen:

Code: Alles auswählen

CompilerIf #PB_Compiler_Unicode
  #Encoding = #PB_UTF8
CompilerElse 
  #Encoding = #PB_Ascii
CompilerEndIf

Define XML$, File$, Output$

#Value$ = "Der Fenstertitel " + Chr(1000) + Chr(1200)
XML$ = "<window text='" + #Value$ + "'></window>"

Output$ = "########## Compose() ##########" + #CRLF$ + #CRLF$
CatchXML(0, @XML$, StringByteLength(XML$), 0, #Encoding)
Output$ + ComposeXML(0) + #CRLF$ + #CRLF$

Output$ + "########## SaveXML() ##########" + #CRLF$ + #CRLF$
File$ = GetTemporaryDirectory() + "XML.xml"
If SaveXML(0, File$) And ReadFile(0, File$) 
  Output$ + ReadString(0, #PB_File_IgnoreEOL | #PB_UTF8)
  CloseFile(0)
  DeleteFile(File$)
EndIf

MessageRequester("XML", Output$)
Mit Ascii-Modus gestartet:

Code: Alles auswählen

########## Compose() ##########

<?xml version="1.0" encoding="ISO-8859-1"?><window text="Der Fenstertitel è°"/>

########## SaveXML() ##########

<?xml version="1.0" encoding="ISO-8859-1"?><window text="Der Fenstertitel ?"/>
Mit Unicode-Modus gestartet:

Code: Alles auswählen

########## Compose() ##########

<?xml version="1.0" encoding="UTF-16"?><window text="Der Fenstertitel ϨҰ"/>

########## SaveXML() ##########

<?xml version="1.0" encoding="UTF-8"?><window text="Der Fenstertitel ϨҰ"/>
Der Encoding-Parameter bei CatchXML() gibt also nicht wie bei PeekS() an, in welcher Codierung der String vom Memory gelesen werden soll - wie ich anfangs dachte -, sondern wie später bei SaveXML() gespeichert werden soll. Entscheidet man sich im Laufe des Codes doch für eine andere Codierung, kann diese mit SetXMLEncoding() geändert werden.
Edit: Wie sich herausgestellt hat, lang ich vorhin doch richtig und der Encoding-Parameter beeinflusst sehr wohl wie der String vom Memory gelesen wird.

Das hier wird nur gemacht, um es einheitlich mit den Standard-Codierungen von ReadString() / WriteString() zu halten:

Code: Alles auswählen

CompilerIf #PB_Compiler_Unicode
  #XmlEncoding = #PB_UTF8
CompilerElse
  #XmlEncoding = #PB_Ascii
CompilerEndIf

Code: Alles auswählen

                      Ascii-Modus         |     Unicode-Modus
--------------------------------------------------------------
Ohne obigem Code:     SaveXML(UTF-8)      |     SaveXML(UTF-8)
--------------------------------------------------------------
Mit obigem Code:      SaveXML(Ascii)      |     SaveXML(UTF-8)

Code: Alles auswählen

Ascii-Modus                         |     Unicode-Modus
-------------------------------------------------------------------------
ReadString / WriteString: Ascii     |     ReadString / WriteString: UTF-8
Edit: Da das oben geschriebene ungültig wurde, ist diese mögliche Begründung ebenfalls zu ignorieren.

Im englischem Forum gemeldet:
CatchXML(): Encoding can be misunderstood
Example codes of OpenXMLDialog: encoding should be changed
Zuletzt geändert von Sicro am 07.05.2016 15:46, insgesamt 2-mal geändert.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
mhs
Beiträge: 224
Registriert: 11.01.2009 16:30
Wohnort: Graben
Kontaktdaten:

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von mhs »

Sicro hat geschrieben:...
Der Encoding-Parameter bei CatchXML() gibt also nicht wie bei PeekS() an, in welcher Codierung der String vom Memory gelesen werden soll - wie ich anfangs dachte -, sondern wie später bei SaveXML() gespeichert werden soll.
...
Das ist leider nicht ganz richtig Sicro. In einem meiner letzten Posts hatte ich auch schon versucht zu erklären, dass die UCS-2 Kodierung uns etwas in die Irre geführt hat. Dort ist es nämlich tatsächlich egal, welcher Wert bei Encoding angegeben wird, der String wird immer richtig gelesen. Wenn du aber z.B. per HTTP einen UTF-8 kodierten String empfängst, dann ist der Parameter Encoding schon entscheidend, ob der String richtig gelesen wird oder nicht.

Mit dem Beispiel aus meinem Post kann man das Szenario eigentlich ganz gut durchspielen.
Michael Hack

Michael Hack Software :: Softwareentwicklung | Webentwicklung | IT-Dienstleistungen
www.michaelhacksoftware.de :: www.mh-s.de :: www.michael-hack.de
Benutzeravatar
Sicro
Beiträge: 968
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: "OpenXMLDialog()"-Beispiel-Codes: merkwürdige Codierunge

Beitrag von Sicro »

Ich habe das Thema eine Weile ruhen lassen und bin nun nochmal herangegangen. Soll manchmal helfen... :mrgreen:

Meine Verwechslungen in den vorherigen Beiträgen habe ich mit Korrekturen versehen.

Das Verhalten von CatchXML() ist für mich aber weiterhin nicht nachvollziehbar.

Code: Alles auswählen

CompilerIf Not #PB_Compiler_Unicode
  CompilerError "Run it in unicode mode!"
CompilerEndIf

XML$ = "<text>Hello?" + Chr(1000) + Chr(1200) + "</text>"
#XML = 0
CatchXML(#XML, @XML$, StringByteLength(XML$, #PB_Unicode), 0, #PB_Ascii)
Debug "CatchXML(#PB_Ascii):   " + ComposeXML(#XML)
FreeXML(#XML)
CatchXML(#XML, @XML$, StringByteLength(XML$, #PB_Unicode), 0, #PB_UTF8)
Debug "CatchXML(#PB_UTF8):    " + ComposeXML(#XML)
FreeXML(#XML)
CatchXML(#XML, @XML$, StringByteLength(XML$, #PB_Unicode), 0, #PB_Unicode)
Debug "CatchXML(#PB_Unicode): " + ComposeXML(#XML)
FreeXML(#XML)

Debug "---------------"
Debug "StringByteLength():            " + Str(StringByteLength(XML$))
Debug "StringByteLength(#PB_Ascii):   " + Str(StringByteLength(XML$, #PB_Ascii))
Debug "StringByteLength(#PB_UTF8):    " + Str(StringByteLength(XML$, #PB_UTF8))
Debug "StringByteLength(#PB_Unicode): " + Str(StringByteLength(XML$, #PB_Unicode))

Debug "----------------"
Debug "PeekS(#PB_Ascii):   " + PeekS(@XML$, -1, #PB_Ascii)
Debug "PeekS(#PB_UTF8):    " + PeekS(@XML$, -1, #PB_UTF8)
Debug "PeekS(#PB_Unicode): " + PeekS(@XML$, -1, #PB_Unicode)

Code: Alles auswählen

[13:19:24] CatchXML(#PB_Ascii):   <?xml version="1.0" encoding="UTF-16"?><text>Hello?ϨҰ</text>
[13:19:24] CatchXML(#PB_UTF8):    <?xml version="1.0" encoding="UTF-16"?><text>Hello?ϨҰ</text>
[13:19:24] CatchXML(#PB_Unicode): <?xml version="1.0" encoding="UTF-16"?><text>Hello?ϨҰ</text>
[13:19:24] ---------------
[13:19:24] StringByteLength():            42
[13:19:24] StringByteLength(#PB_Ascii):   19
[13:19:24] StringByteLength(#PB_UTF8):    23
[13:19:24] StringByteLength(#PB_Unicode): 42
[13:19:24] ----------------
[13:19:24] PeekS(#PB_Ascii):   <
[13:19:24] PeekS(#PB_UTF8):    <
[13:19:24] PeekS(#PB_Unicode): <text>Hello?ϨҰ</text>
Hier ist es für mich unverständlich, warum der Unicode-String "XML$" als Ascii, UTF8 und Unicode gelesen immer korrekte Ausgaben liefert.
Wenn ein Unicode-String in einer anderen Codierung gelesen wird, kann doch eigentlich nichts Sinnvolles ausgegeben werden. Bei PeekS() ist es ja auch so:

Code: Alles auswählen

Text$ = "Das ist der Text°°°°!"

AsciiText$ = PeekS(@Text$, -1, #PB_Ascii)

Debug PeekS(@AsciiText$, -1, #PB_Unicode)
Obiger Code im Ascii-Modus kompiliert:

Code: Alles auswählen

[13:24:04] !
Obiger Code im Unicode-Modus kompiliert:

Code: Alles auswählen

[13:24:43] D

Code: Alles auswählen

Text$ = "<text>Das ist der Text°°°°!</text>"
*Ascii_Memory   = AllocateMemory(StringByteLength(Text$, #PB_Ascii)   + 1, #PB_Memory_NoClear)
*UTF8_Memory    = AllocateMemory(StringByteLength(Text$, #PB_UTF8)    + 1, #PB_Memory_NoClear)
*Unicode_Memory = AllocateMemory(StringByteLength(Text$, #PB_Unicode) + 2, #PB_Memory_NoClear)

If *Ascii_Memory = 0 Or *UTF8_Memory = 0 Or *Unicode_Memory = 0
  End
EndIf

PokeS(*Ascii_Memory,   Text$, -1, #PB_Ascii)
PokeS(*UTF8_Memory,    Text$, -1, #PB_UTF8)
PokeS(*Unicode_Memory, Text$, -1, #PB_Unicode)

Debug "Lese Ascii-String als ..."
If CatchXML(0, *Ascii_Memory, StringByteLength(Text$, #PB_Ascii), 0, #PB_Ascii)
  Debug "-- Ascii: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *Ascii_Memory, StringByteLength(Text$, #PB_Ascii), 0, #PB_UTF8)
  Debug "-- UTF8: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *Ascii_Memory, StringByteLength(Text$, #PB_Ascii), 0, #PB_Unicode)
  Debug "-- Unicode: " + ComposeXML(0)
  FreeXML(0)
EndIf
Debug ""

Debug "Lese UTF8-String als ..."
If CatchXML(0, *UTF8_Memory, StringByteLength(Text$, #PB_UTF8), 0, #PB_Ascii)
  Debug "-- Ascii: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *UTF8_Memory, StringByteLength(Text$, #PB_UTF8), 0, #PB_UTF8)
  Debug "-- UTF8: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *UTF8_Memory, StringByteLength(Text$, #PB_UTF8), 0, #PB_Unicode)
  Debug "-- Unicode: " + ComposeXML(0)
  FreeXML(0)
EndIf
Debug ""

Debug "Lese Unicode-String als ..."
If CatchXML(0, *Unicode_Memory, StringByteLength(Text$, #PB_Unicode), 0, #PB_Ascii)
  Debug "-- Ascii: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *Unicode_Memory, StringByteLength(Text$, #PB_Unicode), 0, #PB_UTF8)
  Debug "-- UTF8: " + ComposeXML(0)
  FreeXML(0)
EndIf
If CatchXML(0, *Unicode_Memory, StringByteLength(Text$, #PB_Unicode), 0, #PB_Unicode)
  Debug "-- Unicode: " + ComposeXML(0)
  FreeXML(0)
EndIf
Obiger Code mit Ascii-Modus kompiliert:

Code: Alles auswählen

[13:21:03] Lese Ascii-String als ...
[13:21:03] -- Ascii: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
[13:21:03] -- UTF8: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text</text>
[13:21:03] -- Unicode: <?xml version="1.0" encoding="ISO-8859-1"?>
[13:21:03] 
[13:21:03] Lese UTF8-String als ...
[13:21:03] -- Ascii: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
[13:21:03] -- UTF8: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
[13:21:03] -- Unicode: <?xml version="1.0" encoding="ISO-8859-1"?>
[13:21:03] 
[13:21:03] Lese Unicode-String als ...
[13:21:03] -- Ascii: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
[13:21:03] -- UTF8: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
[13:21:03] -- Unicode: <?xml version="1.0" encoding="ISO-8859-1"?><text>Das ist der Text°°°°!</text>
Obiger Code mit Unicode-Modus kompiliert:

Code: Alles auswählen

[13:22:08] Lese Ascii-String als ...
[13:22:08] -- Ascii: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
[13:22:08] -- UTF8: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text</text>
[13:22:08] -- Unicode: <?xml version="1.0" encoding="UTF-16"?>
[13:22:08] 
[13:22:08] Lese UTF8-String als ...
[13:22:08] -- Ascii: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
[13:22:08] -- UTF8: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
[13:22:08] -- Unicode: <?xml version="1.0" encoding="UTF-16"?>
[13:22:08] 
[13:22:08] Lese Unicode-String als ...
[13:22:08] -- Ascii: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
[13:22:08] -- UTF8: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
[13:22:08] -- Unicode: <?xml version="1.0" encoding="UTF-16"?><text>Das ist der Text°°°°!</text>
Hier ist es ebenfalls wie oben: Der Unicode-String wird jedes Mal korrekt gelesen. Ascii, UTF8 und Unicode haben doch unterschiedliche Codierungen, wie kann das dann trotzdem funktionieren? :?
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Antworten