Entwickler-Ecke

Dateizugriff - Warum sind Delphi-Textdateien schreibgeschützt?


ueberschecker - Mo 30.08.04 19:39
Titel: Warum sind Delphi-Textdateien schreibgeschützt?
Hallo,

ich schreibe gerade in Delphi7 ein eigentlich ziemlich simples Programm, was mit Textdateien arbeitet. Da ich vorher eigentlich nur in C++ programmiert habe, weiß ich nicht, warum Delphi alle Textdateien, die mit Reset() bzw. Rewrite() geöffnet wurden schreibgeschütz öffnet. So steht es zumindestens in der Hilfe. Das Programm steigt mit E/A-Fehler 105 aus. Was soviel heißt wie Datei wurde nicht zum Schreibem geöffnet. Wenn ich die Datei mit Append() öffne klappt alles ohne Probleme, aber ich möchte ja auch in der Datei was verändern. Wie kann ich den Schreibschutz entfernen? "fileMode:=fmOpenReadWrite" funktioniert nicht.

MfG


Delete - Mo 30.08.04 19:48

Schon mal unter AssignFiel in der Hilfe nachgekuckt?


ueberschecker - Mo 30.08.04 21:20

Also bei mir steht da nichts zum Problem. (Delphi 7 Personal) ich habe jedesmal AssignFile() benutzt bevor ich mit der Datei gearbeitet habe. Also daran kann es nicht liegen.


Delete - Mo 30.08.04 21:23

Bei mir werden die nie schreibgeschützt geöffnet. Wie lautet die genaue Fehlermeldung?


Brueggendiek - Mo 30.08.04 21:31

Hallo!

In Textdateien kann man nichts verändern!

Mit Reset wird die Datei nur zum Lesen geöffnet,
Mit Rewrite wird die Datei so geöffnet, daß sie neu angelegt wird (alter Inhalt gelöscht),
mit Append werden neue Zeilen an die Datei angehängt.

Grund für dieses Verhalten ist, daß die Zeilen ja unterschiedliche Länge haben.

Abhilfe: Wenn nur einzelne Bytes ausgetauscht werden sollen, wird die Datei als "File of Byte" geöffnet. Löschen oder Einfügen von Zeichen ist da nicht möglich!
Werden Zeilen auch in der Länge verändert - reingefügt - gelöscht, kann man mit 2 Dateien arbeiten - den Inhalt der ersten Datei lesen und verändert in die zweite Datei schreiben. Ggf. nachließend Original löschen und Kopie umbenennen.
Außerdem kann man mit TStringList.ReadFromFile die komplette Datei in den Speicher laden und dort bearbeiten. Dann mit SaveToFile wieder speichern.

Bei Dateien mit fester Satzlänge sind typisierte Dateien die richtige Wahl.

Gruß

Dietmar Brüggendiek


ueberschecker - Mo 30.08.04 21:41

Danke,

wenn mich nicht alles täuscht geht das aber unter C++, oder? Dann werd ich das wohl ein bisschen umschreiben müssen.

MfG


ueberschecker - Mo 30.08.04 22:21

Hallo,

ich habe jetzt die Klasse TStringList benutzt. In dem Moment wo ich LoadFromFile() aufrufe gibt es eine Access Violation und das Programm steigt aus. Wenn ich vorher noch Create() aufrufe gibt es eine andere Access Violation. Meiner Meinung nach ist es aber sowieso Blödsinn den Constructor aufzurufen, weil der ja aufgerufen wird, sobald das Object erzeugt wird, jedenfalls ist es in C++ so. In der wunderbaren Hilfe steht jedenfalls nichts zum Thema.
Create() gehört auch zur Klasse TObject und nicht zu TStringList.

MfG


grayfox - Mo 30.08.04 23:00

hallo ueberschecker!
zu deinem beitrag möchte ich mich lieber nicht äussern, sonst artet das gleich wieder in eine diskussion aus, welche programmiersprache besser ist ;)

wenn du die stringlist so erzeugst:




Delphi-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:
type
  TForm1 = class(TForm)
    SpeedButton1: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    MeineListe: TStringList;
  public
    { Public-Deklarationen }
  end;


procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  MeineListe:= TStringList.Create;
  try
    MeineListe.LoadFromFile(Dateiname);

    // mach irgendwas mit der Liste...

    MeineListe.SaveTofile(Dateiname);
  finally
    MeineListe.Free
  end
end;

dann sollte auch die access violation der vergangenheit angehören.


lass mal etwas programmcode sehen...

mfg, stefan


ueberschecker - Di 31.08.04 17:50

Also mein Quellcode sieht so aus:


Delphi-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:
procedure TEditItemFrame.BOKClick(Sender: TObject);
var
    i:integer;
    temp:string;
    strList:TSTringList;
begin
  if bNewItem then begin
    // erzeuge neuen Eintrag (Append())
  end else begin <span style="font-weight: bold"> 
    strList.Create;
    try
     strList.LoadFromFile('C:\Eigene Dateien\auto.txt'{MainFrame.FileName});
     strList[4*datapos]:=EditName.Text;
     strList[4*datapos+1]:=EditLocation.Text;
     strList[4*datapos+2]:=EditChars.Text;
     strList[4*datapos+3]:=EditNumber.Text;
     strList.SaveToFile(MainFrame.FileName);
    finally
     strList.Free;
    end </span>
 end;
  Close;
  MainFrame.ShowData;
end;


Schon beim Aufruf von strList.Create stürzt da Programm ab.

Moderiert von user profile iconUGrohne: Code- durch Delphi-Tags ersetzt.


zorxx - Di 31.08.04 19:07

Hallo,

ersetze mal


Quelltext
1:
strList.Create;                    


durch


Quelltext
1:
strList :=  TStringList.Create;                    


Wie es grayfox in seinem Beispiel beschrieben hat.

Gruss

zorxx


Motzi - Di 31.08.04 20:21

Das ist ein typischer Fehler von Programmierern die aus der C++-Ecke kommen.. ;)
Unter Delphi gibt es keine statischen Objekte, dh. man muss jedes Objekt erst _selbst_ erzeugen bevor man damit arbeiten kann. Jetzt gibt es aber 2 Möglichkeiten den Constructor aufzurufen:

Delphi-Quelltext
1:
2:
3:
4:
5:
var
  aStringList: TStringList;

aStringList.Create;
aStringList := TStringList.Create;

Aber nur der zweite Aufruf erzeugt eine neue Instanz der TStringList-Klasse. Im ersten Fall wird der Constructor als Methode des Objekts aufgerufen, das aStringList referenziert.

Ich hab das hier im Forum schon öfters genauer beschrieben, bei Interesse einfach mal suchen... :)


ueberschecker - Di 31.08.04 20:30

Alles klar. Danke jetzt hab ich das verstanden und das Programm funtioniert auch.

MfG