Seite 2 von 3

Re: WriteData

Verfasst: 14.07.2011 18:15
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.

Re: WriteData

Verfasst: 14.07.2011 18:32
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é

Re: WriteData

Verfasst: 14.07.2011 18:48
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)

Re: WriteData

Verfasst: 14.07.2011 20:15
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.

Re: WriteData

Verfasst: 14.07.2011 21:16
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é

Re: WriteData

Verfasst: 14.07.2011 21:53
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.

Re: WriteData

Verfasst: 15.07.2011 09:15
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

Re: WriteData

Verfasst: 15.07.2011 09:44
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

Re: WriteData

Verfasst: 15.07.2011 10:40
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

Re: WriteData

Verfasst: 15.07.2011 12:19
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