| Autor |
Beitrag |
DaKirsche
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 10:42
Hallo Community,
ich habe schon wieder eine Frage:
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: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75:
| [...] type TLogData = record Index : Integer; Timestamp : TDateTime; HeadLine : String[50]; Short : String[30]; Long : String[255]; User : String[25]; end;
TItems = record Data : File of TLogData; FileName : String; FilePath : String; ItemIndex : Integer; end;
TLog = class function outputGridLine(OutputGrid: TStringGrid; OutputData: TLogData): Boolean; private Items: TItems; function setFile(a_FileName,a_Path: String):Boolean; function goToEof():Boolean; function preventGrid(OutputGrid: TStringGrid):Boolean; function CreateDetailWindow(HForm: TForm): Boolean; public Constructor Create(a_file : String; a_Path: String); Destructor Destroy(); override; function add(a_Data: TLogData):Boolean; function FileName:String; function ItemIndex:Integer; function FilePath:String; function NextLine: Integer; procedure DeleteItem(Index: Integer); function DisplayLogFile(OutputGrid: TStringGrid): Integer; function ShowDetails(Index:Integer;HForm:TForm;InPutGrid: TStringGrid): Boolean; function HideDetailWindow(HForm:TForm;InPutGrid: TStringGrid):Boolean; end; var RowCt: Integer = 0; Hpanel: TPanel; HLabel: array [1..10] of TLabel; HButton: TButton;
implementation [...] procedure TLog.DeleteItem(Index: Integer); var Data: array of TLogData; Data_a: TLogData; isIndex: integer; begin SetLength(Data,NextLine - 2); Reset(Items.Data); isindex:=0; while not Eof(items.Data) do begin Read(Items.Data,data_a); if Data_a.Index<>Index then begin Data[isIndex]:=data_a; Inc(isIndex,1); end; end; Close(Items.Data); DeleteFile(FilePath+FileName); FileCreate(FilePath+FileName); AssignFile(Items.Data,FilePath+FileName); reset(Items.Data); for isindex := 0 to SizeOf(Data)-2 do begin data[isindex].Index:=isindex+1; write(Items.data,data[isindex]); end; end; [...] end. |
Ich will in der o.a. Prozedur einen Eintrag aus einer Datei entfernen. Dabei lese ich alle Datensätze, bis auf den zu löschenden in ein Array ein.
Dann will ich die Quelldatei löschen und schliesse daher die Datei und lösche sie anschliessend.
Danach erstelle ich die Datei neu und befülle die Datei wieder mit den Daten aus dem Array.
Aber dabei tritt ein E/A Fehler 32 auf und nun will ich prüfen, ob die Datei bereits Assigned wurde.
Oder gibt es die Möglichkeit das "EOF" zu "verschieben"? Ich muss das Dateiende ja nur um einen Datensatz nach oben verschieben, dann kann ich das ohne Löschen machen...
Vielen Dank im Voraus!
DaKirsche
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 27.08.07 11:18
Wenn ich dich richtig verstanden habe, würde ich das ganze mit einer TStringList machen, geht viel einfacher:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var SList: TStringList; begin SList := TStringList.Create; SList.LoadFromFile('C:\Test.txt'); SList.Delete(9); SList.SaveToFile('C:\Test.txt'); SList.Free; end; |
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 11:27
Also an und für sich verstehst du mich richtig, aber ich speichere ja ein Record in das File und das enthält dann auch TDateTime und Integer...weiss nicht, ob es dann Probleme geben würde....
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 11:54
Ich habe es jetzt so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TLog.DeleteItem(Index: Integer); var SList: TStringList; path:String; begin path:=Items.FilePath+Items.Filename; Close(Items.Data); SList := TStringList.Create; showmessage(path); SList.LoadFromFile(path);
SList.Delete(Index); SList.SaveToFile(Items.FilePath+Items.Filename); SList.Free; AssignFile(Items.Data,path); |
und ich bekomme einen E/A Fehler 107 : Listenindex überschreitet das Maximum(3). Ich habe 12 Datensätze drin und will Eintrag nr. 3 löschen...
Was ist dran falsch?!?!?
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 27.08.07 13:04
Okay, sorry, dann geht das so nicht und du bekommst den Fehler, weil beim Speichern des records nicht für jedes Item eine neue Zeile angelegt wird und demnach die 10. Zeile != 10. Item ist.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 13:36
Das habe ich leider auch festgestellt^^
Aber kann mir jemand denn sagen, wie ich Prüfen kann, ob der Vorgang AssingFile(FILE); abgeschlossen ist?
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: 26: 27: 28: 29: 30:
| procedure TLog.DeleteItem(Index: Integer); var Data: array of TLogData; Data_a: TLogData; Items_Data:File of TLogData; isIndex: integer; path:String; begin path:=Items.FilePath+Items.Filename; SetLength(Data,NextLine - 2); Reset(Items.Data); isindex:=0; while not Eof(items.Data) do begin Read(Items.Data,data_a); if Data_a.Index<>Index then begin Data[isIndex]:=data_a; Inc(isIndex,1); end; end; Close(Items.Data); DeleteFile(path); while FileExists(path) do Application.ProcessMessages; FileCreate(path); while not FileExists(path) do Application.ProcessMessages; AssignFile(Items.Data,path); reset(Items.Data); for isindex := 0 to SizeOf(Data)-2 do begin data[isindex].Index:=isindex+1; write(Items.data,data[isindex]); end; end; |
Also ich deklariere ja die Variablen, die ich für den Vorgang brauche
Delphi-Quelltext 1: 2: 3: 4:
| var Data: array of TLogData; Data_a: TLogData; isIndex: integer; path:String; |
und dann mach ich folgendes:
Ich speichere den Pfad der aktuellen Datei in den Zwischenspeicher
Delphi-Quelltext 1:
| path:=Items.FilePath+Items.Filename; |
Definiere die Länge des Datenarrays des Zwischenspeichers
Delphi-Quelltext 1:
| SetLength(Data,NextLine - 2); |
Setze den Pointer im File auf Anfang und Indexvariable auf 0
Delphi-Quelltext 1: 2:
| Reset(Items.Data); isindex:=0; |
Nun lese ich jeden Datensatz in das Record, bis FileEnde erreicht
Delphi-Quelltext 1: 2:
| while not Eof(items.Data) do begin Read(Items.Data,data_a); |
Und prüfe jedes Mal, ob der Index der gewählten File (die ID - eindeutiger Wert -) gleich der zu löschenden ist. Ansonsten speichere ich den Datensatz in den nächsten freien Platz im Datensatzzwischenspeicher
Delphi-Quelltext 1: 2: 3: 4: 5:
| if Data_a.Index<>Index then begin Data[isIndex]:=data_a; Inc(isIndex,1); end; end; |
Dann schliesse ich die Datei und lösche diese
Delphi-Quelltext 1: 2: 3:
| Close(Items.Data); DeleteFile(path); while FileExists(path) do Application.ProcessMessages; |
Erstelle die Datei neu
Delphi-Quelltext 1: 2:
| FileCreate(path); while not FileExists(path) do Application.ProcessMessages; |
und greife darauf zu
Delphi-Quelltext 1:
| AssignFile(Items.Data,path); |
Dann setze ich in der Datei den Pointer auf Anfang und schreibe für jeden Datensatz im Zwischenspeicher einen neuen Eintrag rein.
Delphi-Quelltext 1: 2: 3: 4: 5:
| reset(Items.Data); for isindex := 0 to SizeOf(Data)-2 do begin data[isindex].Index:=isindex+1; write(Items.data,data[isindex]); end; |
Aber irgendwie will er mir nicht in die Datei schreiben...erstellen tut er die Datei zwar, aber weiter passiert nix...die Datei bleibt leer.
Dasselbe habe ich auch noch, wenn ich das Programm starte. Die Datei enthält z.B. die Logs der Anmeldungen. Existiert die Datei nicht wird die erstellt...
Aber auch dabei habe ich den E/A Fehler...
Ich denke, dass der Vorgang AssignFile noch nciht abgeschlossen ist, wenn ich Resette und Write...
und mit
Delphi-Quelltext 1:
| function Assigned(var P):Boolean; |
weiss ich nciht, was ich als Parameter übergeben soll...habe schon versucht mit
Delphi-Quelltext 1: 2: 3: 4:
| var p_File: ^File; [...] p_File:=^Items.Data; While not Assigned(p_File) do [...]; |
abver es hat auch nicht geklappt...
Hat wer ne Idee????
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 13:53
Apropos:
Es würde ja auch schon reichen, wenn ich die Datensätze mit
Delphi-Quelltext
in der Datei neu überschreibe, aber dann habe ich ja, wenn ich 10 Datensätze hatte und einen löschen will, der an der Stelle 3 als Beispiel ist:
Datei.name:
Datensatz1
Datensatz2
Datensatz3
Datensatz4
Datensatz5
Datensatz6
Datensatz7
Datensatz8
Datensatz9
Datensatz10
Eof
und ich nun also den 3. Datensatz löschen will und daher immer mit dem Folgenden Datensatz überschreibe folgendes Ergebnis:
Datei.name:
Datensatz1
Datensatz2
Datensatz4
Datensatz5
Datensatz6
Datensatz7
Datensatz8
Datensatz9
Datensatz10
Datensatz10
Eof
Dann müsste ich ja eigentlich nur das Eof um einen Datensatz nach oben verschieben, aber wie mache ich dies der Datei klar?
Ich brächte dann ja Quasi eine Art Aufruf
Delphi-Quelltext
aber das gibt es ja leider nicht....
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 27.08.07 14:33
Moin!
Mal eine konzeptionelle Frage (sonst kann man da schlecht beraten), musst du die Log-Einräge später noch bearbeiten oder bleiben einmal gemachte Einträge statisch?
DaKirsche hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| type TLogData = record Index : Integer; Timestamp : TDateTime; HeadLine : String[50]; Short : String[30]; Long : String[255]; User : String[25]; end; | |
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 14:40
Ne die Einträge bleiben statisch...die werden gespeichert und ausgelesen....nur das löschen einzelner Einträge klappt leider nicht....
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 27.08.07 14:57
Moin!
DaKirsche hat folgendes geschrieben: | | Ne die Einträge bleiben statisch...die werden gespeichert und ausgelesen.... |
Hm, möglicherweise habe ich mich nicht klar genug ausgedrück oder du hast mich falsch verstanden, zur Sicherheit also nochmal: musst du auf die einzelnen Teile eines Logeintrags (womöglich noch schnell) zugreifen oder sind das einfach nur Textzeilen?
DaKirsche hat folgendes geschrieben: | | nur das löschen einzelner Einträge klappt leider nicht.... |
Darum geht´s mir, muss aber erstmal verstehen, was du da machen willst, um eine Alternative vorschlagen zu können.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
DaKirsche 
      
Beiträge: 187
Win XP Pro, SuSe Linux 7.3 - 10.2, Win 2k3 Server, Win 2000, Win NT 4.0
Delphi 2006 Pro, Java, HTML, SQL, PHP, CSS
|
Verfasst: Mo 27.08.07 15:43
Also ich habe meine Datei
File of TLogData
Dieses File befülle ich immer wieder mit neuen Daten...hänge da also immer eue Daten ran.
Die Daten bestehen aus dem o.a. Record TLogData.
Ich muss nicht immer wieder z.B. als Kontrolle, auf die Daten zugriefen solltest du das meinen.
Nur wenn ich die Datensätze ausgeben will muss ich die Datei auslesen und ggf. einen bestimmten Datensatz auslesen.
Also das sieht dann so aus wie HIER.
Es geht darum, dass ich ggf. eine Auflistung habe, wer wann auf das programm zugegriffen hat oder z.B. einen neuen Nutzer angelegt hat o.ä.
Der Zugriff ist nur selten im Lesevorgang und es muss auch nicht schnell sein.
_________________ Die simpelsten Fehler sind meist die Schwersten...
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 27.08.07 16:59
Moin!
DaKirsche hat folgendes geschrieben: | Ich muss nicht immer wieder z.B. als Kontrolle, auf die Daten zugriefen solltest du das meinen.
Nur wenn ich die Datensätze ausgeben will muss ich die Datei auslesen und ggf. einen bestimmten Datensatz auslesen.
[...]
Es geht darum, dass ich ggf. eine Auflistung habe, wer wann auf das programm zugegriffen hat oder z.B. einen neuen Nutzer angelegt hat o.ä.
Der Zugriff ist nur selten im Lesevorgang und es muss auch nicht schnell sein. |
OK, in diesem Fall würde ich das so machen:
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: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
const LOG_FILE = 'C:\Log.txt';
type TLogFile = class(TStringList) public function AddLine(const AHeadline, AShort, ALong, AUser: String): Integer; procedure DecodeLogLine(const AIndex: Integer; var ADateTime: TDateTime; var AHeadline, AShort, ALong, AUser: String); end;
TForm1 = class(TForm) BtnLogEntry: TButton; BtnClearLog: TButton; Memo1: TMemo; BtnGetLine0: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure BtnLogEntryClick(Sender: TObject); procedure BtnClearLogClick(Sender: TObject); procedure BtnGetLine0Click(Sender: TObject); private public LogFile: TLogFile; end;
var Form1: TForm1;
implementation
{$R *.dfm}
function TLogFile.AddLine(const AHeadline, AShort, ALong, AUser: String): Integer; var SL: TStringList; begin SL := TStringList.Create; try SL.Add(DateTimeToStr(Now)); SL.Add(AHeadline); SL.Add(AShort); SL.Add(ALong); SL.Add(AUser); Result := Add(SL.CommaText); finally SL.Free; end; end;
procedure TLogFile.DecodeLogLine(const AIndex: Integer; var ADateTime: TDateTime; var AHeadline, AShort, ALong, AUser: String); var SL: TStringList; begin SL := TStringList.Create; try SL.CommaText := Strings[AIndex]; if (SL.Count = 5) then begin ADateTime := StrToDateDef(SL.Strings[0],0); AHeadline := SL.Strings[1]; AShort := SL.Strings[2]; ALong := SL.Strings[3]; AUser := SL.Strings[4]; end else raise Exception.Create('Invalid log line ('+IntToStr(AIndex)+')!'); finally SL.Free; end; end;
procedure TForm1.FormCreate(Sender: TObject); begin LogFile := TLogFile.Create; if FileExists(LOG_FILE) then LogFile.LoadFromFile(LOG_FILE); end;
procedure TForm1.FormDestroy(Sender: TObject); begin if (LogFile.Count > 0) then LogFile.SaveToFile(LOG_FILE) else DeleteFile(LOG_FILE); LogFile.Free; end;
procedure TForm1.BtnLogEntryClick(Sender: TObject); begin LogFile.AddLine('Test','Kurz','Lang','Ich'); Memo1.Lines.Assign(LogFile); end;
procedure TForm1.BtnClearLogClick(Sender: TObject); begin LogFile.Clear; Memo1.Clear; end;
procedure TForm1.BtnGetLine0Click(Sender: TObject); var DT: TDateTime; Headline,Short,Long,User: String; begin if (LogFile.Count > 0) then begin LogFile.DecodeLogLine(0,DT,Headline,Short,Long,User); ShowMessage('Datum: '+DateTimeToStr(DT)); ShowMessage('Headline: '+Headline); ShowMessage('Short: '+Short); ShowMessage('Long: '+Long); ShowMessage('User: '+User); end; end;
end. |
Wenn du einzelne Zeilen löschen willst, einfach mit z.B. LogFile.Delete(3); die 4. Zeile löschen, fertig.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
christian_u
      
Beiträge: 30
|
Verfasst: Mo 27.08.07 17:21
@Narses man kann und muss nicht alles mit TStringlist machen, das ist hier auch nicht sinvoll.
@Kirsche das was du suchst ist denk ich Truncate, das schneidet die datei an der aktuellen Position ab also den Satzzeiger auf den entsprechenden Eintrag setzen ab dem du löschen willst und dann Truncate aufrufen...
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 27.08.07 17:24
Moin!
christian_u hat folgendes geschrieben: | | @Narses man kann und muss nicht alles mit TStringlist machen, das ist hier auch nicht sinvoll. |
Nun, das liegt zum Glück im Auge des Betrachters  Vorteil meines Ansatzes: die Datei wird vermutlich deutlich kleiner und kann auch mit einem Texteditor eingesehen/bearbeitet werden!
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
christian_u
      
Beiträge: 30
|
Verfasst: Mo 27.08.07 19:03
Richtig, Nachteil deiner Lösung die Datei ist wesentlich schlechter durchsuchbar beim lesen wird wesentlich mehr Speicher benötigt und geparst muss es auch werden was zusätzlich zeit kostet.
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 27.08.07 19:18
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|