UTF8 und Character
-
- Beiträge: 180
- Registriert: 24.09.2010 10:39
UTF8 und Character
Wie ist das eigentlich mit der Char-Größe, also dessen Speichergröße, wenn man ein Programm braucht das sowohl mit UTF8 als auch Ascii klarkommen muss?
In der Hilfe steht dass das Char als Datentyp eine verschieden große Anzahl an Bytes fasst. Je nachdem ob man die Option Unicode-Executable aktiviert hat oder nicht. Wenn man die Option nicht aktiviert hat dann enthält Char immer ein Byte, bei Unicode Executables 2. Man müsste dann also als Unicode Exe kompilieren wenn man Char nutzen will.
UTF8 soll aber bis zu 4 Bytes pro Character brauchen. Wie funktioniert das dann?
...
SizeOf() kann ja die Speichergröße in Byte einer Variable bzw dessen Typ angeben. ZB 2 bei einem Char als Unicode Exe.
Wenn man zB den Zeiger auf das nächste Char in einem String erhalten will dann nutzt man SizeOf() um die entsprechende Anzahl Bytes zu ermitteln die nach vorn gegangen werden muss. Was aber wenn der String ein Ascii-String ist und das Executable im Unicode? Dann würde doch ein Zeichen übersprungen weil die Größe der Unicode-Chars zurückgegeben würde oder? Oder wäre der String dann intern mit leeren Bytes oder so vorgehalten?
In der Hilfe steht dass das Char als Datentyp eine verschieden große Anzahl an Bytes fasst. Je nachdem ob man die Option Unicode-Executable aktiviert hat oder nicht. Wenn man die Option nicht aktiviert hat dann enthält Char immer ein Byte, bei Unicode Executables 2. Man müsste dann also als Unicode Exe kompilieren wenn man Char nutzen will.
UTF8 soll aber bis zu 4 Bytes pro Character brauchen. Wie funktioniert das dann?
...
SizeOf() kann ja die Speichergröße in Byte einer Variable bzw dessen Typ angeben. ZB 2 bei einem Char als Unicode Exe.
Wenn man zB den Zeiger auf das nächste Char in einem String erhalten will dann nutzt man SizeOf() um die entsprechende Anzahl Bytes zu ermitteln die nach vorn gegangen werden muss. Was aber wenn der String ein Ascii-String ist und das Executable im Unicode? Dann würde doch ein Zeichen übersprungen weil die Größe der Unicode-Chars zurückgegeben würde oder? Oder wäre der String dann intern mit leeren Bytes oder so vorgehalten?
Re: UTF8 und Character
Du kannst eine EXE nur als Ascii oder Unicode compilieren.
Das bedeutet das im Speicher entweder nur AsciiStrings liegen oder nur UnicodesStrings.
Damit meine ich die Strings von PureBasic.
UTF8 dient nur dazu selber SpeicherBuffer oder Dateien mit dem UTF8 Format zu beschreiben, um etwas ersparnis gegenüber Unicode zu haben.
Zum konvertieren kannst du PokeS() und PeekS() nutzen mit dne entsprechenden Flags ...
Ein Ascii-String würde in UNICode exe müll ausgeben, außer du konvertierst ihn. dann hätte der UnicodeString im speicher immer Nullen dazwicshen weil Ascii ja nicht über 255 geht ...
EDIT: Ja ein UTF-8 zeichen welches über Unicode $FFFF liegt, wird nicht unterstützt !
Das bedeutet das im Speicher entweder nur AsciiStrings liegen oder nur UnicodesStrings.
Damit meine ich die Strings von PureBasic.
UTF8 dient nur dazu selber SpeicherBuffer oder Dateien mit dem UTF8 Format zu beschreiben, um etwas ersparnis gegenüber Unicode zu haben.
Zum konvertieren kannst du PokeS() und PeekS() nutzen mit dne entsprechenden Flags ...
Ein Ascii-String würde in UNICode exe müll ausgeben, außer du konvertierst ihn. dann hätte der UnicodeString im speicher immer Nullen dazwicshen weil Ascii ja nicht über 255 geht ...
EDIT: Ja ein UTF-8 zeichen welches über Unicode $FFFF liegt, wird nicht unterstützt !
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
-
- Beiträge: 180
- Registriert: 24.09.2010 10:39
Re: UTF8 und Character
Dann wären im Unicodemodus die Stringzeichen immer 2 Byte lang? Oder bis zu 4 und es ist nur das Char dass nicht mehr als 2 Byte pro Zeichen speichern kann?
Ich habe gerade ein wenig getestet mit SizeOf() und die Größe einer gefüllten Stringvariable zurückgeben wollen. In der Hilfe heißt es Speicherverbrauch ist Länge des Strings + 1. Aber SizeOf() gibt immer 4 zurück für die Variable. Sie gibt wohl nicht die Länge des Strings zurück. Vielleicht die Größe der Stringdefinition?
Um die Byteanzahl eines einzelnen Stringzeichens zurückzugeben ist dieser Befehl dann wohl nicht geeignet.
Hat es denn Nachteile wenn man im Unicodemodus kompiliert? ZB RAM-Verbrauch?
Wenn ja dann wäre es vielleicht am Besten wenn man im Asciimodus kompiliert und Strings werden nur mit Funktionen eingelesen bei denen man die Kodierung setzen kann. Um sicherzugehen immer die volle Byte-Größe eines Zeichens einzulesen könnte man dann mit PeekS(*Start, 1, #PB_...) arbeiten. Und der zurückgegebene String sollte mit StringByteLength() die tatsächliche Byteanzahl zurückgeben. Wäre damit vielleicht sogar UTF8 über Unicode $FFFF möglich? Man würde ja nicht mehr mit Char arbeiten. Oder bedeuten die Konstanten einfach nur dass halt immer 2 oder 1 Byte pro Character eingelesen werden?
Was sind das denn für UTF8-Charactere die über Unicode $FFFF liegen? Die sind doch bestimmt nicht alle unwichtig.
Ich habe gerade ein wenig getestet mit SizeOf() und die Größe einer gefüllten Stringvariable zurückgeben wollen. In der Hilfe heißt es Speicherverbrauch ist Länge des Strings + 1. Aber SizeOf() gibt immer 4 zurück für die Variable. Sie gibt wohl nicht die Länge des Strings zurück. Vielleicht die Größe der Stringdefinition?
Um die Byteanzahl eines einzelnen Stringzeichens zurückzugeben ist dieser Befehl dann wohl nicht geeignet.
Hat es denn Nachteile wenn man im Unicodemodus kompiliert? ZB RAM-Verbrauch?
Wenn ja dann wäre es vielleicht am Besten wenn man im Asciimodus kompiliert und Strings werden nur mit Funktionen eingelesen bei denen man die Kodierung setzen kann. Um sicherzugehen immer die volle Byte-Größe eines Zeichens einzulesen könnte man dann mit PeekS(*Start, 1, #PB_...) arbeiten. Und der zurückgegebene String sollte mit StringByteLength() die tatsächliche Byteanzahl zurückgeben. Wäre damit vielleicht sogar UTF8 über Unicode $FFFF möglich? Man würde ja nicht mehr mit Char arbeiten. Oder bedeuten die Konstanten einfach nur dass halt immer 2 oder 1 Byte pro Character eingelesen werden?
Was sind das denn für UTF8-Charactere die über Unicode $FFFF liegen? Die sind doch bestimmt nicht alle unwichtig.
Re: UTF8 und Character
>> Dann wären im Unicodemodus die Stringzeichen immer 2 Byte lang?
Im StringPool von PB ja !
SizeOf(String$) gibt die die größe des Pointers aus (also 4 bei x86)
also entwerden:
StringByteLength(String$, Format)
oder
MemoryStringLength(@String$, Format)
>> Hat es denn Nachteile wenn man im Unicodemodus kompiliert? ZB RAM-Verbrauch?
Naja alle Zeichenketten sind doppelt so lang ... aber so viele wirst du wohl kaum haben.
>> Wenn ja dann wäre es vielleicht am Besten wenn man im Asciimodus kompiliert und Strings werden nur mit Funktionen
>> eingelesen bei denen man die Kodierung setzen kann. Um sicherzugehen immer die volle Byte-Größe eines Zeichens
>> einzulesen könnte man dann mit PeekS(*Start, 1, #PB_...) arbeiten. Und der zurückgegebene String sollte mit
>> StringByteLength() die tatsächliche Byteanzahl zurückgeben. Wäre damit vielleicht sogar UTF8 über Unicode $FFFF
>> möglich? Man würde ja nicht mehr mit Char arbeiten. Oder bedeuten die Konstanten einfach nur dass halt immer 2 oder 1
>> Byte pro Character eingelesen werden?
Auf was willst du eigentlich hinaus ?
Wenn du eine Datei hast in der ein UTF-8 String ist dann liest du den mit ReadString(...#PB_UTF8) ein, damit du sicherstellt, das der String richtig eingelesen wird.
Ob du nun Unicode oder Ascii brauchst hängt davon ab, ob du dnen wirklich "höhere" Sonderzeichen direkt im programm darstellen lassne willst.
Also zB griechische Zeichen in einer MessageBox oder so ...
>> Was sind das denn für UTF8-Charactere die über Unicode $FFFF liegen? Die sind doch bestimmt nicht alle unwichtig.
http://de.wikipedia.org/wiki/UTF-8
Im StringPool von PB ja !
SizeOf(String$) gibt die die größe des Pointers aus (also 4 bei x86)
also entwerden:
StringByteLength(String$, Format)
oder
MemoryStringLength(@String$, Format)
>> Hat es denn Nachteile wenn man im Unicodemodus kompiliert? ZB RAM-Verbrauch?
Naja alle Zeichenketten sind doppelt so lang ... aber so viele wirst du wohl kaum haben.
>> Wenn ja dann wäre es vielleicht am Besten wenn man im Asciimodus kompiliert und Strings werden nur mit Funktionen
>> eingelesen bei denen man die Kodierung setzen kann. Um sicherzugehen immer die volle Byte-Größe eines Zeichens
>> einzulesen könnte man dann mit PeekS(*Start, 1, #PB_...) arbeiten. Und der zurückgegebene String sollte mit
>> StringByteLength() die tatsächliche Byteanzahl zurückgeben. Wäre damit vielleicht sogar UTF8 über Unicode $FFFF
>> möglich? Man würde ja nicht mehr mit Char arbeiten. Oder bedeuten die Konstanten einfach nur dass halt immer 2 oder 1
>> Byte pro Character eingelesen werden?
Auf was willst du eigentlich hinaus ?
Wenn du eine Datei hast in der ein UTF-8 String ist dann liest du den mit ReadString(...#PB_UTF8) ein, damit du sicherstellt, das der String richtig eingelesen wird.
Ob du nun Unicode oder Ascii brauchst hängt davon ab, ob du dnen wirklich "höhere" Sonderzeichen direkt im programm darstellen lassne willst.
Also zB griechische Zeichen in einer MessageBox oder so ...
>> Was sind das denn für UTF8-Charactere die über Unicode $FFFF liegen? Die sind doch bestimmt nicht alle unwichtig.
http://de.wikipedia.org/wiki/UTF-8
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
-
- Beiträge: 180
- Registriert: 24.09.2010 10:39
Re: UTF8 und Character
Das könnte schon viel werden. Es geht um CSV-Dateien die ausgewertet und bearbeitet werden.STARGÅTE hat geschrieben:>> Hat es denn Nachteile wenn man im Unicodemodus kompiliert? ZB RAM-Verbrauch?
Naja alle Zeichenketten sind doppelt so lang ... aber so viele wirst du wohl kaum haben.
>> Wenn ja dann wäre es vielleicht am Besten wenn man im Asciimodus kompiliert und Strings werden nur mit Funktionen
>> eingelesen bei denen man die Kodierung setzen kann. Um sicherzugehen immer die volle Byte-Größe eines Zeichens
>> einzulesen könnte man dann mit PeekS(*Start, 1, #PB_...) arbeiten. Und der zurückgegebene String sollte mit
>> StringByteLength() die tatsächliche Byteanzahl zurückgeben. Wäre damit vielleicht sogar UTF8 über Unicode $FFFF
>> möglich? Man würde ja nicht mehr mit Char arbeiten. Oder bedeuten die Konstanten einfach nur dass halt immer 2 oder 1
>> Byte pro Character eingelesen werden?
Ja die Sonderzeichen brauche ich schon... die Daten enthalten Domains die eben auch zB in thailändischen, russischen usw Buchstaben geschrieben werden. Außerdem Kategorien die natürlich auch in der dem entsprechenden Sprache geschrieben sind. Scheinbar sind diese Sprachen alle in den ersten beiden Byte von UTF8 untergebracht. Das Eurozeichen braucht aber wohl schon 3 Byte und das könnte gut vorkommen.STARGÅTE hat geschrieben:Auf was willst du eigentlich hinaus ?
Wenn du eine Datei hast in der ein UTF-8 String ist dann liest du den mit ReadString(...#PB_UTF8) ein, damit du sicherstellt, das der String richtig eingelesen wird.
Ob du nun Unicode oder Ascii brauchst hängt davon ab, ob du dnen wirklich "höhere" Sonderzeichen direkt im programm darstellen lassne willst.
Also zB griechische Zeichen in einer MessageBox oder so ...
Worauf ich hinaus will ist... ob ich die Exe in Ascii kompilieren kann um zB den Speicherverbrauch nicht zu steigern und gleichzeitig alle UTF8-Zeichen lesen kann selbst wenn sie über 2 Byte lang sind.
Also anstatt ein Char (das ja auf 1 oder 2 Byte beschränkt ist) zu benutzen um ein Zeichen auszulesen dann einen String auslesen der ein Zeichen lang ist und dann eben auch aus 3 oder 4 Byte bestehen kann. ZB mit PeekS(*Start, 1, #PB_...).
Ich habe mal einen Test gemacht. Ich habe das kyrillische Zeichen "з" in einen inputrequester kopiert. Und dann geschaut ob ich das Zeichen so wieder herausbekomme. Code:
Code: Alles auswählen
Define c.Character, s$
s$ = InputRequester("","", "")
c = @s$
Debug Chr(c\c)
Debug s$
Debug PeekS(@s$,2,#PB_UTF8)
Debug StringByteLength(s$)
Debug MemoryStringLength(@s$,#PB_UTF8)
Dann habe ich es als Unicode Executable versucht. (Das gilt doch auch wenn ich nur F5 drücke und keine echte Exe speichere oder?) Und beim Unicode war das Ergebnis identisch.
Bei Eingabe einer 0 gibt es 0,0,0,2,1 aus. Bei Eingabe von "aaa" gibt StringByteLength komischerweise 6 aus. Egal ob ich im Unicodemodus oder im Asciimodus kompiliere...
Daraufhin habe ich das Ganze noch mal mit einem Editorgadget versucht weil die CSV-Daten aus einem Editorgadget gelesen werden sollen und das selbe Ergebnis wie vorher.
Code: Alles auswählen
Define c.Character, s$
*HandleWindowMain = OpenWindow(#PB_Any, 0, 0,700, 400, "URLTool", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered)
*HandleButtonInputToOutput = ButtonGadget(#PB_Any, 5, 167, 30, 30, "V", #PB_Button_MultiLine)
*HandleEditorCSVInput1 = EditorGadget(#PB_Any, 5, 5, 200, 150)
Repeat
EventID = WaitWindowEvent()
If EventWindow() = *HandleWindowMain And EventID = #PB_Event_Gadget
If EventGadget() = *HandleButtonInputToOutput
s$ = GetGadgetText(*HandleEditorCSVInput1)
c = @s$
Debug Chr(c\c)
Debug s$
Debug PeekS(@s$,1,#PB_UTF8)
Debug StringByteLength(s$)
Debug MemoryStringLength(@s$,#PB_UTF8)
EndIf
EndIf
Until EventID = #PB_Event_CloseWindow
Irgendwas passt da noch nicht... Na vielleicht wirds morgen klarer nach etwas Schlaf

- 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: UTF8 und Character
PureBasic Strings sind immer ASCII oder Unicode, aber niemals UTF-8!
UTF-8 kann sich also lediglich in einer Datei oder im Speicher befinden,
wenn Du es als Daten in den Speicher gelesen hast.
Für volle Unicode-Kompatibilität ist es auch empfehlenswert, die IDE auf UTF-8
zu stellen, bzw. sollte dies sowieso der Standard-Modus sein.
UTF-8 aus dem Speicher bekommst Du nur mit entsprechendem Modus bei PeekS,
das Ergebnis ist dann ein String im Format, welches Du in den Compileroptionen
eingestellt hast. Im ASCII-Modus können dabei natürlich Zeichen verloren gehen,
also für Dein Vorhaben ist Unicode in jedem Falle unbedingt erforderlich!
Speicher sparen usw. ist bei heutigen PCs plumpaquatsch und Unicode ist seit W2K
der Standard.
Gruß
Thomas
UTF-8 kann sich also lediglich in einer Datei oder im Speicher befinden,
wenn Du es als Daten in den Speicher gelesen hast.
Für volle Unicode-Kompatibilität ist es auch empfehlenswert, die IDE auf UTF-8
zu stellen, bzw. sollte dies sowieso der Standard-Modus sein.
UTF-8 aus dem Speicher bekommst Du nur mit entsprechendem Modus bei PeekS,
das Ergebnis ist dann ein String im Format, welches Du in den Compileroptionen
eingestellt hast. Im ASCII-Modus können dabei natürlich Zeichen verloren gehen,
also für Dein Vorhaben ist Unicode in jedem Falle unbedingt erforderlich!
Speicher sparen usw. ist bei heutigen PCs plumpaquatsch und Unicode ist seit W2K
der Standard.
Gruß
Thomas
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.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Re: UTF8 und Character
Das Eurozeichen braucht in UTF8 3 Bytes ... weil dort ein paar Bits für die ByteErkennung drauf gehen, in Unicode braucht das Eurozeichen "auch" nur 2 Bytes.Scheinbar sind diese Sprachen alle in den ersten beiden Byte von UTF8 untergebracht. Das Eurozeichen braucht aber wohl schon 3 Byte und das könnte gut vorkommen.
Das ist aber gerade das Problem, ein String hat in ASCII immer genau 1 Byte/Zeichen.Worauf ich hinaus will ist... ob ich die Exe in Ascii kompilieren kann um zB den Speicherverbrauch nicht zu steigern und gleichzeitig alle UTF8-Zeichen lesen kann selbst wenn sie über 2 Byte lang sind.
Also anstatt ein Char (das ja auf 1 oder 2 Byte beschränkt ist) zu benutzen um ein Zeichen auszulesen dann einen String auslesen der ein Zeichen lang ist und dann eben auch aus 3 oder 4 Byte bestehen kann. ZB mit PeekS(*Start, 1, #PB_...).
Wenn du wirklich mit UTF arbeiten möchtest/willst/musst, dann darfst du kein der normalen String-Funktionen nutzen, sonden alles selber "per Hand" über eigene Memorys machen...
So jetzt noch mal zu PeekS und PokeS() und Strings
MODUS: Ascii
Ein Character hat immer 1 Byte!
Ein String (also s$) wird immer Ascii sein. höhere Zeichen gehen einfach verloren werden in das Intervall 0-255 gepresst.
PeekS(@s$,2,#PB_UTF8)
Hier versuchst aus dem Memory wo ein Ascii String drin ist, UTF8 zu lesen, da kommt Müll raus.
StringByteLength(s$) wird immer Zeichen*1Byte ausgeben!
MemoryStringLength(@s$,#PB_UTF8) gibt müll aus!
MODUS: Unicode
Ein Character hat immer 2 Byte!
Ein String (also s$) wird immer Unicode sein.
PeekS(@s$,2,#PB_UTF8)
Hier versuchst aus dem Memory wo ein Unicode String drin ist, UTF8 zu lesen, da kommt Müll raus.
StringByteLength(s$) wird immer Zeichen*2Byte ausgeben!
MemoryStringLength(@s$,#PB_UTF8) gibt müll aus!
Jetzt zum Verständnis:
Code: Alles auswählen
Text$ = "Füße"
*Buffer = AllocateMemory(48)
PokeS(*Buffer, Text$, #PB_Default, #PB_Ascii)
PokeS(*Buffer+16, Text$, #PB_Default, #PB_UTF8)
PokeS(*Buffer+32, Text$, #PB_Default, #PB_Unicode)
ShowMemoryViewer(*Buffer, 48)
Wenn du also wirklich kyrillische Zeichen usw. nutzen willst, musst du im Unicode compilieren, damit die Zeichen nicht verloren gehen, wenn du mit Strings in PB arbeitest.
Ließt du nun zB aber eine UTF8-Datei, musst du dort angeben das du UTF8 lesen willst, und er den String dann zu Unicode macht.
Willst du später wieder nach UTF8 speichern (damit die Datei kleiner ist) musst auch dort UFT8 angeben.
Damit du es nicht falsch verstehst:
Sowas MemoryStringLength(@s$,#PB_UTF8)
gibt dir nicht aus, wieviele Bytes der String unter UTF8 hätte, sonden er versucht UTF8 im Speicher zu lesen und gibt dir dann an wie viele Zeiche er gelesen hat! wenn da natürlich kein UTF8 drin steht, kommt müll raus.
Selbiges gibt für PeekS()
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
-
- Beiträge: 180
- Registriert: 24.09.2010 10:39
Re: UTF8 und Character
Ich muss mir das dann noch mal alles durchlesen und ein paar Testfunktionen schreiben. Danke euch...