Seite 3 von 3

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

Verfasst: 09.04.2016 11:50
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

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

Verfasst: 10.04.2016 15:50
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.

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

Verfasst: 10.04.2016 18:34
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:

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

Verfasst: 17.04.2016 14:36
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

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

Verfasst: 18.04.2016 09:20
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.

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

Verfasst: 08.05.2016 13:58
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? :?