Chr(0) in String verketten und in File schreiben

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

Re: Chr(0) in String verketten und in File schreiben

Beitrag von mk-soft »

Erst die Daten im Memory zusammenstellen (AllocateMemory)
Dann die Daten komplett schreiben (WriteData)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
matbal
Beiträge: 246
Registriert: 30.03.2011 20:53

Re: Chr(0) in String verketten und in File schreiben

Beitrag von matbal »

8 MB Byte für Byte zu schreiben ist nicht das Problem.

Die Stringfunktion Mid() ist zu langsam!
(PureBasic weiß nicht, wie lang ein String ist und liest deshalb bei jedem Aufruf von Mid() den String von Anfang an bis zur Startposition. Könnte ja sein, daß der String kürzer ist als die angegebene Startposition)

Tausche ich Mid() gegen PeekS(), geht es flott.

Eine andere Alternative wäre ein Pointer mit Struktur, mit dem man durch den String läuft.

Geschwindigkeitstest:

Code: Alles auswählen

OpenConsole()
a$ = "001122AABBCCDDEEFF"   ; Teststring 

Repeat
   a$ + a$                 ; Teststring verlängern
Until Len(a$) > 8000000    ; bis über 8 MB

lenght = Len(a$)




t = ElapsedMilliseconds()
For i = 1 To lenght Step 2
   
   ;b$ = Mid(a$, i, 2)      ; < - Langsam
   
   b$ = PeekS(@a$ + (i - 1) * SizeOf(character), 2)  ; < - Schneller
   
   ;byte = Val("$" +b$)
   
   ; Kontrollausgabe, wie schnell die Schleife läuft
   If i % 10000 = 1
      PrintN("Fortschritt: " + Str(i))
   EndIf
   
Next i
PrintN("Zeit: " + Str(ElapsedMilliseconds() - t))
Input()
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Chr(0) in String verketten und in File schreiben

Beitrag von NicTheQuick »

Ich hätte hier noch eine Funktion, die aus einem Unicode-String, der aus Hexzeichen besteht einen Speicherbereich erzeugt mit dem dekodierten Inhalt. Allerdings überprüft er nicht, ob gültige Hexzeichen benutzt werden. Der Prototyp ist nur dazu da, damit man Strings ohne @ übergeben kann, er aber trotzdem nicht kopiert, sondern nur per Referenz weitergegeben wird.
Der Speicherpuffer beginnt mit einer festgelegten Größe (1024) und wird immer wieder verdoppelt, falls nicht mehr alles reinpasst. Das ist ein übliches Verfahren für dynamische zusammenhängende Speicherbereiche.
Am Ende sollte man daran denken den Speicherbereich wieder mit FreeMemory() freizugeben.

Code: Alles auswählen

Prototype.i hex2bin(input.p-unicode)

Procedure.i __hex2bin(*input)
	Protected *i.Character = *input
	Protected bufSize.i = 1024
	Protected *buf = AllocateMemory(bufSize)
	Protected *bufEnd = *buf + bufSize
	Protected *bufTmp
	Protected *o.Ascii = *buf
	Protected state.i = 0
	Protected digit.i
	
	While *i\c
		If *i\c <= '9'
			digit = *i\c - '0'
		Else
			digit = (*i\c & $1f) + 9
		EndIf
		If state = 0
			*o\a = digit << 4
			state = 1
		Else
			*o\a | digit
			state = 0
			*o + 1
			If *o = *bufEnd
				*bufTmp = ReAllocateMemory(*buf, bufSize * 2)
				If Not *bufTmp
					FreeMemory(*buf)
					ProcedureReturn #False
				EndIf
				*buf = *bufTmp
				*o = *buf + bufSize
				bufSize * 2
				*bufEnd = *buf + bufSize
			EndIf
		EndIf
		*i + SizeOf(Character)
	Wend
	
	If *o - *buf = 0
		ProcedureReturn #False
	EndIf
	
	*bufTmp = ReAllocateMemory(*buf, *o - *buf)
	If Not *bufTmp
		FreeMemory(*buf)
		ProcedureReturn #False
	EndIf
	
	ProcedureReturn *bufTmp
EndProcedure

Global hex2bin.hex2bin = @__hex2bin()

s.s = "57696c6c6b6f6d6d656e20696d20507572652d426f61726400"

*a = hex2bin(s)

Debug PeekS(*a, -1, #PB_Ascii)
FreeMemory(*a)
Bild
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Chr(0) in String verketten und in File schreiben

Beitrag von Mijikai »

Hab mal ne lib in fasm gebastelt eventuell besteht ja Interesse :)
Der Code funktioniert nur wenn der Hex-String intakt ist also keine ungültigen Zeichen enthält
und es müssen immer 2 Character Paare (Groß) pro Byte vorliegen.

Code: Alles auswählen

EnableExplicit

;Windows x64 Unicode (uppercase) only!

Import "h2b.lib"
  h2bConvert.i(*Str)
  h2bSize.i(*Buffer)
  h2bFree.i(*Buffer)
EndImport

Global teststring.s
Global *buffer

teststring = "FF00FF"

*buffer = h2bConvert(@teststring)

ShowMemoryViewer(*buffer,3)

Debug h2bSize(*buffer)

Debug h2bFree(*buffer)

End
Download:
https://www.dropbox.com/s/5242otg3qtg3o ... 4.zip?dl=0
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Chr(0) in String verketten und in File schreiben

Beitrag von NicTheQuick »

Wieso eigentlich als Library? Wäre es nicht einfacher das direkt in Inline-ASM zu machen?
Bild
Benutzeravatar
Mijikai
Beiträge: 754
Registriert: 25.09.2016 01:42

Re: Chr(0) in String verketten und in File schreiben

Beitrag von Mijikai »

NicTheQuick hat geschrieben:Wieso eigentlich als Library? Wäre es nicht einfacher das direkt in Inline-ASM zu machen?
Ginge schon aber umständlicher und mit mehr Code.
Keine Freiheiten/Krontrolle im Funktionsaufbau -> man muss dann mit dem Setup von Procedure arbeiten/leben...
Wenn es nur eine ProcedureASM.i () geben würde wo man volle Kontrolle hätte.
Jörg Burdorf
Beiträge: 23
Registriert: 14.12.2018 23:01

Re: Chr(0) in String verketten und in File schreiben

Beitrag von Jörg Burdorf »

Hallo Gemeinde!

Vielen Dank für eure Arbeit, Tips und Anregungen. Hab das Problem jetzt relativ einfach lösen können,
in dem ich mit der Funktion getdatabaseblob die Binärdaten aus der DB2 DB direkt in den Speicher lese
und von da in eine Datei schreiben kann. Geht auch vertretbar schnell. Je nachdem wie groß (Movie) so ein
Blob halt ist.

Hier der Code:

Code: Alles auswählen

  
           If DatabaseQuery(0, insql$, #PB_Database_StaticCursor)
             NextDatabaseRow(0)
             collen = DatabaseColumnSize(0,0)
             *MemoryID = AllocateMemory(collen)
             GetDatabaseBlob(0,0,*MemoryID,collen)
             If *MemoryID
               OpenFile(0,dsname$)
               WriteData(0,*MemoryID,collen)
               CloseFile(0)
               FreeMemory(*MemoryID)
             EndIf
           EndIf
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Chr(0) in String verketten und in File schreiben

Beitrag von NicTheQuick »

Und wir denken die ganze Zeit dieser Blob besteht aus Hexadezimaldaten. Wieso hast du nicht gleich gesagt, dass das ein binärer Blob ist?
Bild
Jörg Burdorf
Beiträge: 23
Registriert: 14.12.2018 23:01

Re: Chr(0) in String verketten und in File schreiben

Beitrag von Jörg Burdorf »

Sorry! Hatte zuerst mit GetDatabaseString probiert,da kamen die Daten in Hex zurück. Erst bei
größeren BLOBs gab es dann Probleme.

Jetzt tut.

Sorry nochmal. War da auf dem Holzweg.

Habe aber wieder was dazu gelernt.

LG
Jörg
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Chr(0) in String verketten und in File schreiben

Beitrag von NicTheQuick »

:allright:
Bild
Antworten