Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zeilenweise in Datei Schreiben (https://www.delphipraxis.net/56176-zeilenweise-datei-schreiben.html)

Evian 1. Nov 2005 23:03


Zeilenweise in Datei Schreiben
 
Hallo Zusammen,

ich möchte in einer Datei die ersten beiden Zeilen mit bestimmten Strings überschreiben. Ich dachte, das geht so:

Delphi-Quellcode:
assignfile(f,filename);
reset(f);
append(f);
for i := 0 to 1 DO
begin
  writeln(f,neueStrings[i]);
end;
closefile(f);
aber er hängt die Strings einfach hinten an die Datei an. Wie genau überschreibe ich eine Zeile?!

gruß

Evian

3_of_8 1. Nov 2005 23:06

Re: Zeilenweise in Datei Schreiben
 
Append; setzt die Einfügemarke automatisch ans Ende der Datei. Tu das raus.

Evian 1. Nov 2005 23:10

Re: Zeilenweise in Datei Schreiben
 
mh.. das ist mir echt peinlich, aber ich habe seid der Schule nicht mehr Zeileweise gelsen und geschrieben, mit den Methoden von den einzelnen Listen in Delphi war mir der Zugriff immer lieber, da so schön einfach. Diesmal sind die Dateien zu groß um sie komplett mit readfromfile() zu laden.

Tscha und was soll ich sagen, wenn ich append weg lasse, bekomme ich einen E/A-Fehler 105.

Edit: ich schätze ich muss die Einfüge marke dann selber setzen, aber finde hier im Forum nicht wie.. *g*

3_of_8 1. Nov 2005 23:12

Re: Zeilenweise in Datei Schreiben
 
Hmmm... Seltsam... Ich habe Append noch nie gebraucht. Was genau ist denn ein E/A 105?

EDIT: Was ist dir peinlich? Das ein Totalnewb deine Frage beantwortet hat?

Evian 1. Nov 2005 23:15

Re: Zeilenweise in Datei Schreiben
 
Zitat:

Zitat von 3_of_8
EDIT: Was ist dir peinlich? Das ein Totalnewb deine Frage beantwortet hat?

Woher soll ich wissen, dass Du ein newbie bist?! Und außerdem spielt das für mich keine Rolle, denn wenn Du mir hilfst das Problem zu lösen freue ich mich um so mehr. Ich programmiere nur schon fast 4 Jahre mit Delphi und die Sache ist eigendlich schon recht rudimentär... habs aber einfach vergessen, wie's geht :)


der Fehler sagt follgendes:

"Datei wurde nicht für Ausgabe geöffnet" -> Wird von Write oder Writeln für eine Textdatei gemeldet, wenn keine Konsolenanwendung generiert wird.

ich schätze, ich muss die Einfüge marke noch auf die erste Zeile setzen, aber wie?!

Luckie 1. Nov 2005 23:17

Re: Zeilenweise in Datei Schreiben
 
Zitat:

Zitat von 3_of_8
Was genau ist denn ein E/A 105?

delphi-Hilfe:
Zitat:

105 File not open for output Reported by Write or Writeln on a text file if you do not generate a Console application.
Trifft davon was zu:
Zitat:

Reset opens the existing external file with the name assigned to F using the mode specified by the global FileMode variable. An error results if no existing external file of the given name exists or if the file can’t be opened with the current file mode. If F is already open, it is first closed and then reopened. The current file position is set to the beginning of the file.
Und was passiert hier bei:
Delphi-Quellcode:
AssignFile(f,filename);
{$I-}
Reset(f);
if IOResult = 0 then
begin
  for i := 0 to 1 DO
  begin
    WriteLn(f,neueStrings[i]);
  end;
  CloseFile(f);
end
else
  ShowMessage(SysErrorMessage(GetLastError));
{$I+}

Evian 1. Nov 2005 23:24

Re: Zeilenweise in Datei Schreiben
 
mh.. also ich lese erst die ersten beiden ZEilen aus, schreibe sie dann in ein Memo und schreibe sie dann wieder Rückwerts ind die Datei. Also zumindest habe ich das vor :).

Bei Deinem Code gibt es im ersten durchlauf keinen Fehler, aber es wird auch nicht in die Datei geschrieben... wenn ich direkt noch mal lesen will gibt es wieder den E/A-Fehler:

hier mal der Testcode:

Delphi-Quellcode:
function reverse(s : STRING): STRING;
VAR
i : Integer;
BEGIN
  for i := length(s) Downto 0 do
  BEGIN
    result := result + s[i];
  END;
END;

function getdata(filename:string):TStrings;
var f:text;
    s:string;
    i:integer;
begin
result:=TStringList.create;
assignfile(f,filename);
reset(f);
for i := 0 to 1 DO
begin
  readln(f,s);
  result.add(s);
end;
closefile(f);
end;

procedure setData(filename:string);
var f:text;
    s:string;
    i:integer;
begin
AssignFile(f,filename);
{$I-}
Reset(f);
if IOResult = 0 then
begin
  for i := 0 to 1 DO
  begin
    WriteLn(f,reverse(Form1.memo1.lines[i]));
  end;
  CloseFile(f);
end
else
  ShowMessage(SysErrorMessage(GetLastError));
{$I+}
end;

procedure TForm1.Button1Click(Sender: TObject);
BEGIN
  Memo1.Lines.AddStrings(getdata('c:/TCPCheckResult.txt'));
  setData('c:/TCPCheckResult.txt');
END;

Evian 1. Nov 2005 23:59

Re: Zeilenweise in Datei Schreiben
 
ok, wenn man in einer Datei Daten Überschreiben will, dann muss man rewrite(); nutzen..., aber dann wird die Datei auch komplett neu geschrieben. ISt es nicht möglich einfach nur bestimmte Zeilen einer Datei zu überschreiben?!

Luckie 2. Nov 2005 00:01

Re: Zeilenweise in Datei Schreiben
 
Aber dass der PathSeparator unter Windows eigentlich der BackSlash ist weißt du?

Evian 2. Nov 2005 00:18

Re: Zeilenweise in Datei Schreiben
 
Zitat:

Zitat von Luckie
Aber dass der PathSeparator unter Windows eigentlich der BackSlash ist weißt du?

Mh.. das hört sich ein wenig vorwurfsvoll an.
Also ich wusste es nicht und ich gebe zu, dass ich in dem Bereich noch weniger Ahnung habe, als ich ohne hin schon dachte, aber ganz ehrlich ich habe keine Ahnung, wie mir diese Information hier weiter helfen soll. Könntest Du das bitte erläutern.

Gruß

Evian

EDIT: Ok ´jetzt hab ich erst gerafft, was Du meinst. Entschuldige manchmal sieht man den Wald vor lauter Bäumen nicht.

Luckie 2. Nov 2005 00:20

Re: Zeilenweise in Datei Schreiben
 
Das Zeichen unter Windows zum Trennen von verzeichnissen und dateien ist der "\" und nicht der "/", dass auch der "/" funktioniert liegt an der Verspieltheit der damaligen DOS Entwickler bei Microsoft, die etwas Unix like haben wollten. Man sollte aber nicht darauf vertrauen, dass er auch immer akzeptiert wird, da eben der offizielle PathSeparator der "\" ist.

Aber was heißt du wußtest das nicht? Noch nie einen Pfad in der Konsole oder damals noch unter DOS eingegeben? :gruebel:

Evian 2. Nov 2005 00:28

Re: Zeilenweise in Datei Schreiben
 
Doch wusste ich schon, aber ich habe in letzter ZEit viel mit Linux gearbeitet und diese Sache einfach übersehen. PathSeparator hat sich im ersten Moment einfach nur etwas seltsam angehört und deshalb konnte ich damit nicht gleich etwas anfangen. (um die Uhrzeit ist mein Gehirn warscheinlich bei 5% Leistungsfähigkeit oder so angekommen ^^)
Nun gut, aber trotz alledem bleibt der Fehler der selbe.

Also nur zum Verständniss. Ist es unter Windows mit Delphi überhaupt möglich, bestimmte Zeilen einer Textdatei zu ändern, ohne dass man die gesammte Datei in den Hauptspeicher laden muss?! Und wenn ja, könnte vielleicht jemand einen kleinen CodeBeispiel posten, wie ich das mache? Weil mit dem Code, den ich jetzt habe, geht es nicht...

Luckie 2. Nov 2005 00:39

Re: Zeilenweise in Datei Schreiben
 
Du kannst nicht gleichzeitig aus einer datei lesen und in sie reinschreiben. Geh über eine Temporäredatei.

marabu 2. Nov 2005 06:28

Re: Zeilenweise in Datei Schreiben
 
Hallo Evian,

hier hast du ein wenig Code, der dir das Prinzip zeigt:

Delphi-Quellcode:
procedure PrependLines(s: TStrings; fileName: string);
var
  fs: TFileStream;
  fn: string;
begin
  SetLength(fn, MAX_PATH);
  if GetTempFileName('.', 'TMP', 0, @fn[1]) = 0
    then raise Exception.Create(SysErrorMessage(GetLastError))
    else SetLength(fn, Pred(Pos(#0, fn)));
  fs := TFileStream.Create(fileName, fmOpenRead, fmShareDenyWrite);
  with TFileStream.Create(fn, fmCreate) do
  begin
    Write(s.GetText^, StrLen(s.GetText));
    CopyFrom(fs, fs.Size);
    Free;
  end;
  fs.Free;
  DeleteFile(fileName);
  RenameFile(fn, fileName);
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
const
  fn = 'c:\daten\temp.txt';
begin
  with Memo.Lines do
  begin
    Clear;
    Add('123');
    Add('abc');
  end;
  PrependLines(Memo.Lines, fn);
end;
Grüße vom marabu

Evian 2. Nov 2005 15:41

Re: Zeilenweise in Datei Schreiben
 
also prinziepel kann ich hiermit schreiben, aber es wird nicht überschrieben, sondern quasi die Zeielen "123" und "abc" in die erste und zweite ZEile der Datei geschrieben und der Rest dann weiter nach unten verschoben. Also nach dem bearbeiten hat die Datei x also 2 Zeilen mehr als vor dem bearbeiten. Ich möchte aber keine neuen informationen vorhängen, sondern direkt die erste und zweite Zeile überschreiben.

marabu 2. Nov 2005 16:31

Re: Zeilenweise in Datei Schreiben
 
Ersetzen kannst du bestimmte Zeilen so:

Delphi-Quellcode:
procedure ReplaceLines(
  s: TStrings;         // Ersatzzeilen
  fileName: string;    // Name einer existierenden Textdatei
  iStart: cardinal     // Zeilennummer, Beginn der Ersetzung, ab 0 gezählt
);
const
  BUFSIZE = 32 * 1024;
var
  fIn, fOut: TextFile;
  fn, line: string;
  iCount, iStop: cardinal;
  bufIn, bufOut: array of byte;
begin
  SetLength(fn, MAX_PATH);
  if GetTempFileName('.', 'TMP', 0, @fn[1]) = 0
    then raise Exception.Create(SysErrorMessage(GetLastError))
    else SetLength(fn, Pred(Pos(#0, fn)));
  AssignFile(fIn, fileName);
  Reset(fIn);
  SetLength(bufIn, BUFSIZE);
  SetTextBuf(fIn, bufIn[0]);
  AssignFile(fOut, fn);
  Rewrite(fOut);
  SetLength(bufOut, BUFSIZE);
  SetTextBuf(fOut, bufOut[0]);
  iCount := 0;
  iStop := iStart + s.Count;
  while not Eof(fIn) do
  begin
    ReadLn(fIn, line);
    if (iCount < iStart) or (iCount >= iStop)
      then WriteLn(fOut, line)
      else WriteLn(fOut, s[iCount - iStart]);
    Inc(iCount);
  end;
  CloseFile(fIn);
  CloseFile(fOut);
  DeleteFile(fileName);
  RenameFile(fn, fileName);
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
const
  fn = 'c:\daten\temp.txt';
begin
  with Memo.Lines do
  begin
    Clear;
    Add('123');
    Add('abc');
  end;
  // Zeilen 1 und 2 werden ersetzt, 0 bleibt erhalten
  ReplaceLines(Memo.Lines, fn, 1);
end;
saftey code musst du selbst einbauen. Die Ersetzung von nicht existierenden Zeilennummern wird einfach ignoriert.

Grüße vom marabu


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:21 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