Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Daten mit AssignFile ändern oder anfügen (https://www.delphipraxis.net/56051-daten-mit-assignfile-aendern-oder-anfuegen.html)

Ralf Stehle 31. Okt 2005 12:28


Daten mit AssignFile ändern oder anfügen
 
Ich möchte an einer ganz bestimmten Stelle einer Binärdatei Daten einfügen. Falls diese Daten schon vorhanden sind, sollen Sie überschrieben werden, falls die Daten nicht vorhanden sind, müssen Sie ans Ende der Datei angehängt werden

Mit AssignFile habe ich es immerhin schon geschafft, eine Datei zu kopieren und dabei die Daten zu ändern:

Delphi-Quellcode:
var Buffer: array[1..2048] of byte;
    NumRead, NumWritten, i : Integer;
    q,z: File;
    s: string;
    c: char;
begin
   AssignFile(q, SelectedRoot + SelectedFile,'.001')); Reset(q, 1);
   AssignFile(z, SelectedRoot + SelectedFile,'.002')); Rewrite(z, 1);

   BlockRead(q, Buffer, SizeOf(Buffer), NumRead);

   for i:=23430 to 180 do begin
     s := Copy(EditNachname.Text, i-23430, 1);
     if s='' then Buffer[i]:= 0 else Char(Buffer[i]):= s[1]
   end;

   BlockWrite(z, Buffer, NumRead, NumWritten);

  repeat
    BlockRead(q, Buffer, SizeOf(Buffer), NumRead);
    BlockWrite(z, Buffer, NumRead, NumWritten);
  until (NumRead = 0) or (NumWritten <> NumRead);

  CloseFile(q);
  CloseFile(z);
end.
Falls die Dateiposition 23430 (und die Bytes danach) nicht vorhanden sind, soll der Inhalt von Edit1.Text genau an der Position 23430 drangehängt werden

Ich schaffe das leider nicht ohne eure Hilfe, da ich eigentlich nicht genau verstehe, was Numread und NumWritten in der Repeat-Schleife genau bewirken

Vielen Dank

Ralf

ichbins 31. Okt 2005 12:37

Re: Daten mit AssignFile ändern oder anfügen
 
numread und numwrite sind zwei Variablen, in die gespeichert wird, wie viele Bytes tatsächlich gelesen oder geschrieben wurden. Die kannste auch weglassen, aber dann kommt ne Exception wenn er nicht so viele Bytes schreiben/lesen kann wie du ihm sagst.

Die Schleife
Delphi-Quellcode:
for i:=23430 to 180 do begin
kann gar nicht gehen, da er nicht von 23430 bis 180 HOCHzählen kann. Du musst statt to downto nehmen.

An die Datei anhängen geht auch mit blockwrite.

Um ans Ende einer Datei zu springen, machst du

Delphi-Quellcode:
  seek(f,filesize(f));
was die For-Schleife macht, weiss ich jetzt nicht? In BUF sind ja nur die ersten 2048 Bytes der Datei gespeichert...
Wie kannst du dann auf das Byte nr.23430 zugreifen? da kommt doch eh ein Fehler?

Der_Unwissende 31. Okt 2005 12:59

Re: Daten mit AssignFile ändern oder anfügen
 
Hey,
ich glaube du kannst das alles viel leichter realisieren, indem du auf AssignFile verzichtest und ein TMemoryStream-Objekt benutzt. Da hast du einen Zeiger auf Memory, was halt wirklich der Speicherbereich ist, den du möchtest. Ein TStream hat immer eine Größe (size) mit der du gleich weißt, wie groß deine Datei ist (und ist auch noch schnell).
Mein Ansatz wäre es, dass du dir ein solches TMemoryStream Objekt anlegst. Dann noch ein Array dyn. Größe, dass setzt du auf das Maximum von der reelen Dateigröße und der Größe, die eine Datei hätte wenn du deine Bytes schreibst und dann kopierst du mit CopyMememory (WindowsApi) einfach den inhalt der Datei in dieses Array.
In diesem Array änderst du die Stellen, die du ändern möchtest und schreibst das Array einfach in den Stream (den Inhalt vorher löschen oder ab Position := 0 schreiben).

Hab leider gerade kein Delphi da und kann dir nicht wirklich ein Bsp. schicken, aber vielleicht später, hoffe ist grob klar?
Sonst einfach nochmal fragen.

Gruß Der Unwissende

marabu 31. Okt 2005 13:02

Re: Daten mit AssignFile ändern oder anfügen
 
Mit einem FileStream würde es etwa so funktionieren:

Delphi-Quellcode:
procedure WriteString(fileName, s: string; pos: cardinal);
begin
  if FileExists(fileName) then
    with TFileStream.Create(fileName, fmOpenWrite, fmShareDenyWrite) do
    begin
      Position := pos;
      Write(s[1], Length(s));
      Free;
    end;
end;
Grüße vom marabu

Der_Unwissende 31. Okt 2005 13:12

Re: Daten mit AssignFile ändern oder anfügen
 
Weil ich mir gerade nicht sicher bin, kann ich Pos > Size setzen? Müsste ich glatt mal in die Hilfe schauen, klingt so unsauber. Und war Size sogar ein Property mit write?

Ralf Stehle 31. Okt 2005 13:37

Re: Daten mit AssignFile ändern oder anfügen
 
Vielen Dank für die Tipps, die Idee mit dem Filestream muss ich mal probieren, sieht ja recht logisch aus.

Die Schleife for i:=23430 to 180 war ein Tippfehler, es sollte heißen for i:=23430 to Length(Edit1.text), ich wollte nur zeigen, dass ich genau am Byte 23430 die Zeichen einfügen möchte

Der_Unwissende 31. Okt 2005 13:41

Re: Daten mit AssignFile ändern oder anfügen
 
Ok, hier mal mit MemoryStream

Delphi-Quellcode:
var MemoryStream : TMemoryStream;
    buffer : Array of Byte;
begin
  // Memorystream anlegen
  MemoryStream := TMemoryStream.Create;
  // Datei laden
  MemoryStream.LoadFromFile(FILENAME);

  // Maximum aus schon existierender Dateigröße und Datei mit 23430 Byte +
  // Länge des angehangenen Textes
  setLength(buffer, max(23430 + length(self.Edit1.Text), MemoryStream.Size));

  // kopieren der schon vorhandenen bytes aus der Datei
  if MemoryStream.Size > 0 then
    begin
      copyMemory(@buffer[0], MemoryStream.Memory, MemoryStream.Size);
    end; // if size(MemoryStream) > 0

  // schreibt Edit1.Text an die Stelle 23430 (also beginnend bei)
  // überschreibt auch alles was schon vorhanden ist
  copyMemory(@buffer[23430], PChar(self.Edit1.Text), length(self.Edit1.Text));
 
  // löschen der alten Daten und rücksetzen der Position im Stream
  MemoryStream.Clear;
  // schreibt alle erzeugten Daten
  MemoryStream.Write(buffer[0], length(buffer));
  // abspeichern
  MemoryStream.SaveToFile(FILENAME);
  // aufräumen
  MemoryStream.Free;
Gut, für max brauchst du die Unit Math und FILENAME musst du natürlich anpassen. An sich kann man da sicher noch einiges sauberer und schöner machen, ab guck erstmal ob es das ist was du möchtest. Insbesondere solltest du buffer natürlich mit 0en oder etwas anderem Definiertem füllen, denn sonst kann es natürlich sein dass da etwas unerwartetes steht und bei irgendeiner Auswertung mal nicht egal ist. Wie gesagt, es würden jetzt auch alle Daten die schon drin standen beibehalten werden. Das heißt natürlich auch, dass wenn du schon einen längeren Edit1.Text z.B. '123' abgespeichert hast und den mit '45' überschreibst stünde in der Datei ab 23430 '453', die würde also nicht überschrieben werden!
Natürlich sollte die 23430 auch als CONST definiert werden, macht Änderungen schöner, wie gesagt guck erstmal

Gruß Der Unwissende

marabu 31. Okt 2005 13:49

Re: Daten mit AssignFile ändern oder anfügen
 
Hallo Unwissender,

Zitat:

Zitat von Der_Unwissende
kann ich Pos > Size setzen? ... Und war Size sogar ein Property mit write?

sogar das geht: klick

Freundliche Grüße vom marabu

Der_Unwissende 31. Okt 2005 14:17

Re: Daten mit AssignFile ändern oder anfügen
 
@marabu Hey, praktisch, danke. Hab es mir gerade in der etwas na ja formulierten Hilfe angeschaut, da steht dass die Zuweisung bei TStream wirkungslos ist und bei abgeleiteten Klassen überschrieben werden kann, toll. Heißt das nicht letztlich, dass man es je nach Ableitung probieren muss? Geh aber jetzt davon aus, dass alle bekannten Ableitungen (insbesondere TFile- und TMemorystream) das können.

Gruß


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:24 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz