WriteData

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: WriteData

Beitrag von HeX0R »

Hast du mal probiert, das ganze erst ins Temp-Verzeichnis zu schreiben, und dann die ganze Datei einfach rüberzuschieben?

Wobei sich auch die Frage stellt, wieviel Bytes du überhaupt patchen willst.
Wenn das nur so nen Muckefuck ist, kannst du doch gleich die Datei per OpenFile() öffnen und die paar Bytes direkt in der Originaldatei patchen.
Benutzeravatar
Elektrolurch
Beiträge: 168
Registriert: 11.10.2007 16:48
Wohnort: 49°26'51.46"N - 8°59'49.06"E
Kontaktdaten:

Re: WriteData

Beitrag von Elektrolurch »

Hi HeXOR

Ja das Rüberschieben geht.
Im Prinzip sind es nur 20 Stellen in der 4,88MB Datei.
Aber wie schreibe ich an die richtige Stelle?
Neu schreiben, ans Ende hängen kenne ich, aber gezielt an eine Stelle leider nicht, deswegen habe ich ja diesen Weg eingeschlagen.

BYe André
Wer Rechtschreibfehler findet darf sie ruhig behalten, ich brauche sie nicht mehr, ich habe noch genug davon.
BildBildBild
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: WriteData

Beitrag von HeX0R »

Elektrolurch hat geschrieben: Im Prinzip sind es nur 20 Stellen in der 4,88MB Datei.
Aber wie schreibe ich an die richtige Stelle?
Das ist auch kein Hexenwerk:

Code: Alles auswählen

If OpenFile(0, "\\192.168.1.7\import\A")
	*Dateiinhalt = AllocateMemory(Lof(0))
	If *Dateiinhalt
		ReadData(0, *Dateiinhalt, Lof(0))
		For i = 0 To Lof(0) - 10
			If PeekS(*Dateiinhalt + i, 10) = "Alter Text"
				FileSeek(0, i)
				WriteString(0, "Neuer Text")
			EndIf
		Next i
		FreeMemory(*Dateiinhalt)
	EndIf
	CloseFile(0)
EndIf
Falls der gesuchte Datenblock nur einmal vorkommt, kannst du nach dem auffinden auch via Break aus der Schleife springen,
um das nicht unnötig in die Länge zu ziehen.

Noch besser wäre (weil du ja die Datei immer erst übers Netz ziehen musst), nur Blockweise einzulesen, aber dann wird es einen Tick aufwändiger.

Der Vollständigkeithalber:

Code: Alles auswählen

Procedure PatchFile(File.s, *MemToFind, *MemToSet, MemLength, BlockSize = 1024)
	Protected FID, i, Size, Pos.q, *Buffer, Result

	If FileSize(File) > 0
		FID = OpenFile(#PB_Any, File)
		If FID
			*Buffer = AllocateMemory(BlockSize)
			If *Buffer
				Pos = 0
				Repeat
					Size = ReadData(FID, *Buffer, BlockSize)
					For i = 0 To Size - MemLength - 1
						If CompareMemory(*Buffer + i, *MemToFind, MemLength)
							FileSeek(FID, Pos + i)
							WriteData(FID, *MemToSet, MemLength)
							Result = #True
							Break 2
						EndIf
					Next i
					Pos + Size - MemLength
					FileSeek(FID, Pos)
				Until Size < BlockSize
				FreeMemory(*Buffer)
			EndIf
			CloseFile(FID)
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

If PatchFile("\\192.168.1.7\import\A", @"Alter Text", @"Neuer Text", StringByteLength("Alter Text"))
	Debug "O.k., Successfully patched!"
EndIf
(Beide Codes ungetestet)
Zuletzt geändert von HeX0R am 15.07.2011 12:38, insgesamt 1-mal geändert.
ullmann
Beiträge: 205
Registriert: 28.10.2005 07:21

Re: WriteData

Beitrag von ullmann »

Da ein anderer - von Dir nicht genutzter Befehl - nämlich ReceiveHTTPFile(URL$, Dateiname$) bei einigen Nutzern vorzeitig abbricht, wäre mal zu prüfen, ob dieser Fehler nicht auch bei FileSize in Verbindung mit einem Netzlaufwerk auftritt.

Code: Alles auswählen

;Einlesen
Dateilaenge.l = FileSize("\\192.168.1.7\import\A")
Du könntest also nach diesen beiden Codezeilen mal mit "Debug Dateilaenge" prüfen, ob die Variable Dateilaenge auch bei großen Dateien, die übers Netzwerk abgefragt werden, richtig ermittelt wird.
Benutzeravatar
Elektrolurch
Beiträge: 168
Registriert: 11.10.2007 16:48
Wohnort: 49°26'51.46"N - 8°59'49.06"E
Kontaktdaten:

Re: WriteData

Beitrag von Elektrolurch »

Hi

Nein Nein das Einlesen klappt schon, sieht man ja daran, daß ich patchen kann und das Schreiben auf die anderen Laufwerke klappt.

BYe André
Wer Rechtschreibfehler findet darf sie ruhig behalten, ich brauche sie nicht mehr, ich habe noch genug davon.
BildBildBild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: WriteData

Beitrag von STARGÅTE »

Vielleicht bringen dich ja die Befehle:
FileBuffersSize()
und
FlushFileBuffers()
weiter.

Habe damit selber noch nie gearbeitet, aber sie sind halt u.a. dafür da, das wirkliche Schreiben zu beeinflussen.
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
Benutzeravatar
Elektrolurch
Beiträge: 168
Registriert: 11.10.2007 16:48
Wohnort: 49°26'51.46"N - 8°59'49.06"E
Kontaktdaten:

Re: WriteData

Beitrag von Elektrolurch »

Hi HeXOR

Ich habe mich entschlossen deinen 2ten Code zu benutzen da er deutlich schneller ist als der 1te.
Leider kamen noch zwei kleinere Fehler hoch, die ich unten korrigieren mußte.

1. EndProcedure fehlte.
2. Wenn der gesuchte Text nicht gefunden wurde, weil schon gepatched, lief die suche über das Ende der Datei hinaus.

leider habe ich nun ein neues kleines Problem.
Die Zeichenkette kommt 2 Mal in der Datei vor.
Ich weiß zwar, dass ich die erste ändern muß und könnte dies auch ausnützen und mit dem Break heraus springen.
Im nächsten Anlauf würde aber dann die Routine die zweite Zeichenkette patchen. :cry:
Wenn ich meine Zeichenkette erweitern könnte, wäre das möglich, das Problem ist aber, dass als Trenner ein NUL kommt.
Ursprünglich hatte ich auch einen etwas längeren Suchstring gebastelt.
In etwa so

Code: Alles auswählen

If PeekS( *Dateiinhalt + I, 20) = "gesuchter Text" + Chr(NUL) + "Mehr text"
aber beim Procedureaufruf geht das ja nicht mehr.
Wie kann man das anpassen?
Schon mal ein Danke an alle die sich bislang beteiligt haben.

BYe André

Code: Alles auswählen

Procedure PatchFile(File.s, *MemToFind, *MemToSet, MemLength, BlockSize = 1024)
   Protected FID, i, Size, Pos.q, *Buffer, Result

   If FileSize(File) > 0
      FID = OpenFile(#PB_Any, File)
      If FID
         *Buffer = AllocateMemory(BlockSize)
         If *Buffer
            Pos = 0
            Repeat
               Size = ReadData(FID, *Buffer, BlockSize)
               For i = 0 To Size - MemLength - 1
                  If CompareMemory(*Buffer + i, *MemToFind, MemLength)
                     FileSeek(FID, Pos + i)
                     WriteData(FID, *MemToSet, MemLength)
                     Result = #True
                     Break 2
                  EndIf
               Next i
               Pos + Size - MemLength                                                                     ;Pos + BlockSize - MemLength
               FileSeek(FID, Pos)
            Until Size < BlockSize
            FreeMemory(*Buffer)
         EndIf
         CloseFile(FID)
      EndIf
   EndIf

   ProcedureReturn Result
EndProcedure                                                                                                    ;EndIf

If PatchFile("\\192.168.1.7\import\A", @"Alter Text", @"Neuer Text", StringByteLength("Alter Text"))
   Debug "O.k., Successfully patched!"
EndIf
Wer Rechtschreibfehler findet darf sie ruhig behalten, ich brauche sie nicht mehr, ich habe noch genug davon.
BildBildBild
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: WriteData

Beitrag von ts-soft »

Elektrolurch hat geschrieben: Ursprünglich hatte ich auch einen etwas längeren Suchstring gebastelt.
In etwa so

Code: Alles auswählen

If PeekS( *Dateiinhalt + I, 20) = "gesuchter Text" + Chr(NUL) + "Mehr text"
aber beim Procedureaufruf geht das ja nicht mehr.
Dir ist hoffentlich klar, das hier nur mit "gesuchter Text" verglichen wird!

Code: Alles auswählen

Define *mem = AllocateMemory(25)

PokeS(*mem, "gesuchter Text", 14)
PokeS(*mem + 15, "Mehr text")

If PeekS(*mem, 25) = "gesuchter Text" + Chr(0) + "ist jetzt egal, was hier steht" 
  Debug "Gefunden"
EndIf
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
Elektrolurch
Beiträge: 168
Registriert: 11.10.2007 16:48
Wohnort: 49°26'51.46"N - 8°59'49.06"E
Kontaktdaten:

Re: WriteData

Beitrag von Elektrolurch »

Hi

ich hatt es nicht gemerkt weil es ja eh nur 2 Mal vorkommt und die erste die richtige war und ich dann die Routine verließ.

Mittlerweile habe ich mir wieder ein Suchmuster gebastelt, das Scheint zu funktionieren.
Ich kann zumindest die beiden möglichen Treffer unterscheiden und den richtigen patchen, ich erkenne sogar mittlerweile ob schon gepatched wurde und das schreiben auf dem Ziellaufwerk klappt auch.

Wenn nichts mehr unerwartetes kommt, wäre ich fürs erste mal zufrieden.

Code: Alles auswählen

Define *mem = AllocateMemory(25)
Define *such = AllocateMemory(25)

PokeS(*mem, "gesuchter Text", 14)
PokeS(*mem + 15, "Mehr text")

PokeS(*such, "gesuchter Text", 14)
PokeS(*such + 15, "Mehr dext")

If CompareMemory(*mem, *such, 25)
  Debug "Gefunden"
Else
  Debug "nicht Gefunden"
EndIf
Wer Rechtschreibfehler findet darf sie ruhig behalten, ich brauche sie nicht mehr, ich habe noch genug davon.
BildBildBild
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: WriteData

Beitrag von Kiffi »

@Elektrolurch: mir scheint, als ob Dein Problem durch die Verwendung einer Datenbank
recht einfach gelöst werden kann (beispielsweise mit SQLite; ist in PB schon eingebaut) .
Dadurch würdest Du Dir zumindest das Patchen der Datendatei sparen und Du müsstest
nicht mehr mit Dateizeigern arbeiten.

Nur so als Alternativvorschlag ... Kiffi
a²+b²=mc²
Antworten