Entwickler-Ecke

Dateizugriff - Problem mit Bin-Patchen


Biarchiv - So 02.02.03 18:35
Titel: Problem mit Bin-Patchen
Hallo,

Habe folgendes Problem mit BlockRead and BlockWrite. Wolte nach bestimmten (rrrrrrr) in einer Datei suchen. Nach diesen Zeichencodes soll die Datei 30000 Bytes nach diesen String per Zufall mit welchen Zeichencodes gepatched werden ohne das die Datei größer werden darf.

Bur leider habe ich da einen Fehler drin.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
  fsFrom,fsTo : TFilestream;
  u,u1 : string;
  size1 : integer;
  f: file;
  l,l1 : Longint;

begin
  if not Fileexists(Edit1.Text) then
    begin
    showmessage('Can not open file.');
    exit;
    end;
    u := 'rrrrrrr';
    u1 := 'f';
    AssignFile(f, Edit1.Text);
    Reset(f, 1);
    size1 := GetFileSize(Edit1.Text);
    for l := 3000 to size1 do
    begin
      Seek(f, l);
      BlockRead(f, u[1], Length(u));
      if u = ''rrrrrrr'' then
        begin
        for l1 := 1 to 28000 do
        begin
        BlockWrite(f, u1[1], 1);
        end;
        end;
     end;
     CloseFile(f);

Ist es auch möglich einen 1-100% Anzeige in einen Label1.Caption zu bekommen?

Danke..


Delete - Mo 03.02.03 09:55

Biarchiv hat folgendes geschrieben:
Bur leider habe ich da einen Fehler drin.

Verrätst du auch, welchen? - Deine Beschreibung sagt was anderes aus als der von dir gepostete Code, und schon deshalb würde ich auf mehrere Fehler tippen. Nur, damit ich das hier verstehe:
Zitat:
Wolte nach bestimmten (rrrrrrr) in einer Datei suchen. Nach diesen Zeichencodes
soll die Datei 30000 Bytes nach diesen String per Zufall mit welchen Zeichencodes
gepatched werden ohne das die Datei größer werden darf.

Bis zum ersten Satz komme ich noch mit. Du suchst 7 R's ("rrrrrrr") in einer Datei. Wenn du die gefunden hast, dann ... hm, dein Text sagt: du willst 30.000 Bytes nach dem gefundenen String irgendwelche Zufallszeichen schreiben. Dein Code dagegen schreibt, gleich nach den 7 R's!, 28.000x das F in die Datei.

Tipps


Biarchiv - Mo 03.02.03 20:15

Hallo,

Kann statt rrrrrr auch gdfgdfg sein.
Ich wolte eine bestimmte Zeichenkette in einer Datei suchen und finden
und 32000 Bytes ab und mit dieser Zeichencodes zB mit ffh überschreiben.

Und dann weiter suchen bis Ende der File.


Delete - Mo 03.02.03 21:01

Na ja. Und Ideen, wie man´s richtig machen könnte und was man vermeiden sollte, habe ich dir ja genannt.


Biarchiv - Mi 05.02.03 20:38

Hallo,

Habe folgendes geschrieben und es Überschreibt die Dateienen nur hängt es sich nach dem
patch auf. Es reagiert nicht mehr. Ist die Endloss schleife falsch.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
function Patch1(const FileName: TFileName): Boolean;
var
  l,l1: Longint;
  u,u1: string;
  f: file;
  size1: integer;
begin
  Result := False;
  u := 'testtest';
  u1 := 'f';
  size1 := GetFileSize(FileName);
//  size1 := size1 - 10;
  AssignFile(f, FileName);
  Reset(f, 1);
  l := 0;
  for l := 0 to size1 do
  begin
    Seek(f, l);
    BlockRead(f, u[1], Length(u));
    if u = 'testtest' then
    begin
      for l1 := 0 to 28000 do
      begin
      BlockWrite(f,u1[1], Length(u1));
      end;
    end;
  end;
  CloseFile(f);
end;


Delete - Do 06.02.03 09:38

Irgendwie sehe ich keinen großen Unterschied zu deinem ersten Versuch.
Eine Endlosschleife sehe ich auch nicht. :?

Schau dir doch einfach mal das BlockRead/BlockWrite-Beispiel in der Hilfe an und benutze es als Anregung/Grundlage/Idee/...


Biarchiv - Do 06.02.03 10:26

Hallo,

Normal müßte es passen aber leider laut Delphi-Debuger erhängt sich das Proggi immer.

Vieleicht habe ich da irrgendo eine break oder so vergessen?
Oder sucht er dann immer wieder von Anfang an?


Delete - Do 06.02.03 14:27

Eigentlich nicht, da du ja den Schleifenwert als Offset benutzt. Trotzdem ist dieser Weg zu umständlich und zu langsam. Nimm den hier (der sieht nur so lang aus, weil ich ihn gründlich kommentiert habe):

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
var
  f      : file;
  u      : array[0..65535]of char;
  lPos   : longint;
  iRead,
  iWrite : integer;
begin
  {$I-}
  AssignFile(f,ExtractFilePath(paramstr(0)) + 'binary.dat');
  ReSet(f,1);

  if(IoResult = 0) then begin
    repeat
      // aktuelle Position merken, & 8 Bytes lesen
      lPos := filepos(f); BlockRead(f,u,8,iRead);

      // waren es 8 Bytes?
      if(iRead = 8) then begin
        // ist es das Wort "testtest"?
        if(lstrcmp(u,'testtest') = 0) then begin
          // debugger
          ShowMessage(Format('"%s" at position %d',[u,lPos]));

          // Puffer mit F's füllen, & 28.000 Stück schreiben
          fillchar  (u,sizeof(u),'f');
          BlockWrite(f,u,28000,iWrite);
          // Fehler beim Schreiben (evtl. Dateiende!);
          // Schleife verlassen
          if(iWrite <> 28000) then break;

          // Puffer auf #0 zurücksetzen; sonst wird nicht
          // mehr korrekt weitergemacht
          fillchar  (u,sizeof(u),#0);
          // das liegt an der Funktion "lstrcmp", die zwei PChars
          // (null-terminiert) miteinander vergleicht. Wenn der
          // Puffer aber lauter F's enthält, entsteht beim erneuten
          // Einlesen der Datei ein String wie
          //
          //  testtestfffffffffffffffffffffffffff....
          //
          // Folglich stimmt die Bedingung nicht mehr!
        end else
        // es war nicht das Wort "testtest";
        // Suchposition um Eins erhöhen
          Seek(f,lPos+1);
      end;
    until(iRead = 0);

    CloseFile(f);
  end;
  {$I+}
end;

Allerdings: das überschreibt nicht das gesuchte Wort (in dem Fall: "testtest"). Aber irgendwas musst du ja auch tun ... :)


Biarchiv - Do 06.02.03 20:00

Hallo,

Danke an MathiasSimmack.

Danke für den Code.
Habe den Fehler gefunden nur leider geht dein Code auch nicht
wenn die Datei so 100 - 500 MB groß ist.

Was müßte ich da ändern um so große files patchen zu können
mit Deinen Code.


Delete - Fr 07.02.03 09:29

Es sollte schon gehen, es dauert nur etwas länger. 100 bis 500 meg wollen ja erst mal durchsucht werden.

Idee #1: Nach dem "Seek(f,lPos+1)" baust du ein "Application.ProcessMessages" ein. Damit bleibt deine Anwendung bedienbar, bzw. sie hängt sich nicht auf.
Die Anwendung hängt sich nicht wirklich auf! Wenn sie mit kleinen Dateien funktioniert, dann arbeitet sie auch große Brummer ab. Es fehlt in dem Fall nur an der Rückmeldung für Windows. Dadurch wird die Anwendung im TaskMan fälschlich (oder irreführend) als "reagiert nicht" dargestellt; aber wenn du in aller Ruhe abwartest, geht es tadellos.
Nun, wie auch immer: das "reagiert nicht"-Problem löst du mit dem Aufruf von "Application.ProcessMessages".

Idee #2: Progressbar einbauen. Die Dateigröße kannst du ja ermitteln; die aktuelle Position wird ermittelt; also - anzeigen lassen!

Und zur Laufzeit bitte die Buttons deaktivieren, damit der User zwar das Fenster rumschieben, aber nicht irgendwelche anderen Funktionen auslösen kann.


Delete - Fr 07.02.03 09:38

Ein Application.ProcessMessages bremst aber auch das Programm aus, da der Thread immer wieder in die Nachrichtenschleife geschickt wird, um zu kucken, ob was vorliegt.

Wenn große Dateien keine Ausnahme sind, würde ich das ganze in einen separaten Thread auslagern.


Delete - Fr 07.02.03 09:56

Nur wenn man es zu oft aufruft!

Man könnte z.B. auch prüfen, ob die Datei einen bestimmten Schwellenwert (z.B. 10meg) überschreitet. In dem Fall sorgt man dafür, dass z.B. alle 20 oder 30 Durchläufe einmal "Application.ProcessMessages" aufgerufen wird.