Autor Beitrag
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Mi 12.11.03 09:57 
Oft benötigt man die Möglichkeit eine Logdatei zu erstellen und Einträge in dieser zu machen. Die folgende Unit (LogFile.pas) stellt ein Objekt zur Verfügung über welches man ein Logfile automatisch erstellen lassen kann und mit bestimmten Methoden Einträge in die Datei einfügen kann.

Die Methoden WriteHint, WriteError, etc sind dafür da um einen Eintrag in die Logdatei einzufügen. Mit Hilfe der Methoden BeginSection und EndSection kann man innerhalb der Logdatei für etwas mehr Übersichtlichkeit sorgen.

Hier ein Beispiel wie man mit dem tLogFile Objekt arbeiten kann:
ausblenden 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:
Uses
  LogFile, SysUtils;

{...}

Var
  LogFile: tLogFile;
Begin
  LogFile := tLogFile.Create ('c:\test.log');
  Try
    LogFile.WithDebug := FindCmdLineSwitch ('DebugLog', ['/'], True);
    LogFile.WriteHint ('Program start');
    LogFile.BeginSection;

    {...}

    LogFile.EndSection;
    LogFile.WriteHint ('Program end');
  Finally
    LogFile.Free;
  End;

End;

Hier nun die Unit LogFile.pas:
ausblenden volle Höhe 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:
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:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
Unit LogFile;

Interface

Type
  // Legt fest als was der Eintrag im Logfile markiert werden soll
  tLogFileLineTypeId = (
      idLogFileLineTypeDebug,    // Debug
      idLogFileLineTypeHint,     // Hinweis
      idLogFileLineTypeWarning,  // Warunung
      idLogFileLineTypeError     // Fehler
    );

  tLogFile = Class
      Private
        fFile: TextFile;
        fSectionLevel: Integer;
        fWithDebug: Boolean;

        Procedure WriteLine (aType: tLogFileLineTypeId; aText: String);
      Public
        Constructor Create (aFilename: String);
        Destructor Destroy;  override;

        // Nach dem Aufruf von BeginSection werden die Einträge im Logfile
        // um weitere 2 Leerstellen eingerückt gespeichert.
        Procedure BeginSection;
        // Nach dem Aufruf von EndSection werden die Einträge im Logfile
        // um 2 Leerstellen weniger eingerückt gespeichert.
        Procedure EndSection;

        // Schreibt einen Debug-Eintrag in das Logfile. Allerdings nur wenn das
        // Property WithDebug auf True gesetzt ist.
        Procedure WriteDebug (aText: String);
        // Schreibt einen Hinweis-Eintrag in das Logfile.
        Procedure WriteHint (aText: String);
        // Schreibt einen Warung-Eintrag in das Logfile.
        Procedure WriteWarning (aText: String);
        // Schreibt einen Fehler-Eintrag in das Logfile.
        Procedure WriteError (aText: String);
        // Schreibt ein leere Zeile in das Logfile.
        Procedure WriteEmptyLine;

        // Gibt an ob Debug-Einträge gespeichert werden sollen.
        Property  WithDebug: Boolean read fWithDebug write fWithDebug;
    End;

Implementation

Uses
  SysUtils;

Constructor tLogFile.Create (aFilename: String);
Begin
  AssignFile (fFile, aFileName);

  // Wenn die Datei bereits existiert werden Daten angehängt.
  If FileExists (aFilename) Then
    Append (fFile)
  Else
    Rewrite (fFile);

  fSectionLevel := 0;
  fWithDebug := False;
End;

Destructor tLogFile.Destroy;
Begin
  CloseFile (fFile);

  Inherited;
End;

Procedure tLogFile.WriteLine (aType: tLogFileLineTypeId; aText: String);
Const
  cTypeChar : Array [tLogFileLineTypeId] Of Char = ('D'' ''*''!');

    Function GetSpace (aLength: Integer): String;
    Var
      Str: String;
    Begin
      Str := '';

      While Length (Str) < aLength Do
        Str := Str + #32;

      GetSpace := Str;
    End;

Var
  Str: String;
Begin
  If (aType = idLogFileLineTypeDebug) and Not fWithDebug Then
    Exit;

  Str := FormatDateTime ('yy/mm/dd hh:nn:ss', Now);
  Str := Str + #32 + cTypeChar [aType] + #32 + GetSpace (fSectionLevel * 2) + aText;

  WriteLN (fFile, Str);
End;

Procedure tLogFile.WriteDebug (aText: String);
Begin
  WriteLine (idLogFileLineTypeDebug, aText);
End;

Procedure tLogFile.WriteHint (aText: String);
Begin
  WriteLine (idLogFileLineTypeHint, aText);
End;

Procedure tLogFile.WriteWarning (aText: String);
Begin
  WriteLine (idLogFileLineTypeWarning, aText);
End;

Procedure tLogFile.WriteError (aText: String);
Begin
  WriteLine (idLogFileLineTypeError, aText);
End;

Procedure tLogFile.WriteEmptyLine;
Begin
  WriteLN (fFile, '');
End;

Procedure tLogFile.BeginSection;
Begin
  Inc (fSectionLevel);
End;

Procedure tLogFile.EndSection;
Begin
  Dec (fSectionLevel);
  If fSectionLevel < 0 Then
    fSectionLevel := 0;
End;

End.
Ja-Pa
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 458

Win XP, Suse 9.3
D1, D3, D5 Std, D7 Pro, D2005 Pers, Kylix 3
BeitragVerfasst: So 31.10.04 13:20 
Find ich gut! Ich hab mir selber eine solche Unit programmiert, aber deine gefällt mir wegen Begin-/EndSection besser. Werde sie gleich testen.

Grüße,
Ja-Pa

_________________
Der Autor dieses Textes haftet nicht für Schäden an Soft- oder Hardware
oder Vermögensschäden, die durch das Benutzen des Textes entstehen.
Maweki
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 197

Ubuntu Linux
Lazarus
BeitragVerfasst: So 31.10.04 13:55 
ich hab mir eine selbstgeschrieben. Mir gefaellt immer diese geschichte mit dem erstellen eines neuen Objekts nicht.

Ich habe es so geloest, dass man mit Wildcards sich seinen eigenen Aufbau des Logfiles machen kann. Also man kann die Endung bestimmen, wie die Logdatei heissen soll, und wie die Eintraege aufgebaut sein sollen. Ihr koennt sie euch ja mal ansehen...

Man kann dann einfach mit AddLogEntry(Text); einen Leogeintrag nach einem durch Wildcards bestimmten Schema machen. Diese Prozedur ist mit einer zusaetzlichen Option, der Zeit ueberlagert. So kann man auch Logeintraege in Spielzeit machen...

dazu gibt es drei Schemate, Normaler Eintrag, Alarm und Kommentar. Halt jeweils mit Individuell aenderbarem Schema. Ich denke aber, dass ich schon gute Defaults gesetzt habe...

ausblenden volle Höhe 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:
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:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
{Wildcards:                     Examples
CaseSensivity is ON
$Y = Year of the TDateTime      2004  1999
$M = Month of the TDateTime     08    11
$D = Day of the TDateTime       02    30

$h = Hour of the TDateTime      03    17
$m = Minute of the TDateTime    07    45
$s = Second of the TDateTime    06    32
$k = Millisecond of TDateTime   008   580

$t = InputText. No Replace!!
}

unit Log;

interface
  procedure SetFilePath(Path: string);
  function GetFilePath: string;

  procedure SetLogFileExtension(ext: string);
  function GetLogFileExtension: string;

  procedure SetLogFileNameStructure(Structure: string);
  function GetLogFileNameStructure: string;

  procedure SetLogEntryStructure(Structure: string);
  function GetLogEntryStructure: string;

  procedure SetLogCommentStructure(Structure: string);
  function GetLogCommentStructure: string;

  procedure SetLogAlertStructure(Structure: string);
  function GetLogAlertStructure: string;

  procedure AddLogEntry(Text: string);overload;
  procedure AddLogEntry(Text: string; Time: TDateTime);overload;

  procedure AddLogComment(Text: string);overload;
  procedure AddLogComment(Text: string; Time: TDateTime);overload;

  procedure AddLogAlert(Text: string);overload;
  procedure AddLogAlert(Text: string; Time: TDateTime);overload;

  function GetCurrentLogFileName: string;

  function WildcardToText(Wildcard: string): string;

implementation

uses Classes, SysUtils, DateUtils;

var
  FilePath: string = 'Logs\';
  LogFileExt: string = 'log';
  FileNameStructure: string = '$Y-$M-$D';
  LogEntryStructure: string = '$h:$m:$s - $t';
  CommentStructure: string = '--- $t ---';
  AlertStructure: string = '### $h:$m:$s ### $t ###';
  ProgDir: string = '';
  InputText: string = '';

procedure GetProgPath;
begin
  if ProgDir = '' then
    ProgDir := ExtractFilePath(ParamStr(0));
end;

procedure SendToInputText(Text: string);
begin
  InputText := Text;
end;

procedure WriteToFile(Text, RelativePath, FileName: string);
var
  f:Textfile;
  size:longint;
  s: string;
begin
  s := '';
  GetProgPath;
  If not DirectoryExists(ProgDir + relativePath) then
    ForceDirectories(ProgDir + relativePath);
  {$I-}
  assignfile(f, ProgDir + relativePath + FileName);    
  Append(f);
  if ioresult<>0 then
    rewrite(f);

  writeln(f,Text);    
  closeFile(f);
  {$I+}
end;

function replaceText(Text: string; Time: TDateTime): string;
var
  EndResult: string;
begin
  Result := '';
  EndResult := StringReplace(Text, '$Y', FormatDateTime('yyyy', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$M', FormatDateTime('mm', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$D', FormatDateTime('dd', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$h', FormatDateTime('hh', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$m', FormatDateTime('nn', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$s', FormatDateTime('ss', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$k', FormatDateTime('zzz', Time),
    [rfReplaceAll]);
  EndResult := StringReplace(EndResult, '$t', InputText, [rfReplaceAll]);
  
  Result := EndResult;
end;

procedure SetFilePath(Path: string);
  function CheckBackSlash(const AFilename: String): String;
  begin
  if Length(AFilename)=0 then
    begin
      Result:=AFilename;
      Exit;
    end;

  if AFilename[Length(AFilename)]<>'\' then
    Result:=AFilename+'\'
  else
    Result:=AFilename;
  end;
begin

  FilePath := CheckBackslash(Path);
end;

// ------------------------------- Get 'n Set -------------------------------

function GetFilePath: string;
begin
  Result := FilePath;
end;

procedure SetLogFileExtension(ext: string);
begin
  If Ext[1] = '.' then
    Delete(Ext, 11);
  SetLength(Ext, 3);
  LogFileExt := ext;
end;

function GetLogFileExtension: string;
begin
  Result := LogFileExt;
end;

procedure SetLogFileNameStructure(Structure: string);
begin
  FileNameStructure := Structure;
end;

function GetLogFileNameStructure: string;
begin
  Result := FileNameStructure;
end;

procedure SetLogEntryStructure(Structure: string);
begin
  LogEntryStructure := Structure;
end;

function GetLogEntryStructure: string;
begin
  Result := LogEntryStructure;
end;

procedure SetLogCommentStructure(Structure: string);
begin
  CommentStructure := Structure;
end;

function GetLogCommentStructure: string;
begin
  Result := CommentStructure;
end;

procedure SetLogAlertStructure(Structure: string);
begin
  AlertStructure := Structure;
end;

function GetLogAlertStructure: string;
begin
  Result := AlertStructure;
end;

// ------------------------------- Get 'n Set ----------------------------END
// -------------------------------- Log Add's --------------------------------
procedure AddLogEntry(Text: string);
begin
  AddLogEntry(Text, now);
end;

procedure AddLogEntry(Text: string; Time: TDateTime);
var
  Filename, EntryText: string;
  Zeit: TDateTime;
begin
  SendToInputText(Text);
  Zeit := Time;
  FileName := ReplaceText(FileNameStructure, Zeit) + '.' + LogFileExt;
  EntryText := ReplaceText(LogEntryStructure, Zeit);
  WriteToFile(EntryText, FilePath, FileName);
end;

procedure AddLogComment(Text: string);
begin
  AddLogComment(Text, now);
end;

procedure AddLogComment(Text: string; Time: TDateTime);
var
  Filename, EntryText: string;
  Zeit: TDateTime;
begin
  SendToInputText(Text);
  Zeit := Time;
  FileName := ReplaceText(FileNameStructure, Zeit) + '.' + LogFileExt;
  EntryText := ReplaceText(CommentStructure, Zeit);
  WriteToFile(EntryText, FilePath, FileName);
end;

procedure AddLogAlert(Text: string);
begin
  AddLogAlert(Text, now);
end;

procedure AddLogAlert(Text: string; Time: TDateTime);
var
  Filename, EntryText: string;
  Zeit: TDateTime;
begin
  SendToInputText(Text);
  Zeit := Time;
  FileName := ReplaceText(FileNameStructure, Zeit) + '.' + LogFileExt;
  EntryText := ReplaceText(AlertStructure, Zeit);
  WriteToFile(EntryText, FilePath, FileName);
end;

function GetCurrentLogFileName: string;
begin
  GetProgPath;
  Result := ProgDir + FilePath + replaceText(FileNameStructure, now) + '.' +
    LogFileExt;
end;

function WildcardToText(Wildcard: string): string;
begin
  Result := Replacetext(Wildcard, now);
end;

end.


Ich denke, es sollte ersichtlich sein.
Und sry an Tino, dass ich seinen Thread missbrauche..
mehmeh
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97

WIN XP
D5 Prof
BeitragVerfasst: Do 28.07.05 15:02 
also ich steig da nicht ganz durch.

Ich soll in mein Programm noch ein LogFile hinanbringen. Allerdings wollte ich mir nicht einfach den code heraus kopieren.

Ich dachte mir eher ich kann mir eine Variable als Textdatei deklarieren und das dann als .log speichern. und bei jedem button1 oder button2 betätigen schreibt der das entsprechende hinein. Oder mach ich es mir zu einfach?
Maweki
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 197

Ubuntu Linux
Lazarus
BeitragVerfasst: Do 28.07.05 17:41 
das kannst du natuerlich so machen, mit einer TStringList und soweiter, aber das bringt insofern nichts, da du die ganze Datei immer wieder einliest und schreibst bzw. nur komplett schreibst. Und das ist sehr langsam. Und eine (relativ) Schnelle Prozedurensammlung haben hier Tino und ich geliefert.

Wohingegen Tino einen anderen Ansatz hat als ich. Er ersellt durch OOP ein neues Objekt was selbst in seine eigene Datei schreibt. Mein Ansatz hingegen ist ein Logfile was sich seinen Namen selbst sucht, ohne OOP...
mehmeh
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97

WIN XP
D5 Prof
BeitragVerfasst: Fr 29.07.05 10:49 
nun ja ich will es ja mit dem versuchen, was ich hier gefunden habe. Nur habe ich nun das Problem, das ich nicht weiß wie ich das in mein Programm gekonnt einbinde und es letzlich die Daten, die meines erachtens in das logfile geschrieben werden sollen auch hineinkommen. :?:
Maweki
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 197

Ubuntu Linux
Lazarus
BeitragVerfasst: Fr 29.07.05 10:58 
du nimmst entweder meinen oder Tinos Code und machst ihn in eine eigene Unit speicherst sie und schreibst die bei den uses rein.

Benutzt du einfach eine Prozedur (bei mir) fuer den Eintrag. Bei Tino musst du vorher noch ein Objekt erstellen...
mehmeh
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97

WIN XP
D5 Prof
BeitragVerfasst: Fr 29.07.05 11:32 
ah jetzt hab ich es endlich kapiert. Ich hab deinen Code genommen, weil ich nicht weiß was ich bei Tinos Code noch für ein Objekt erstellen muss.

Habe also eine Unit draus gemacht, gespeichert, bei mir in mein Programm hinzugefügt und in die Uses geschrieben.
Und jetzt nur noch AddLogEntry('Start....'); hinschreiben, für welche Procedure was hinein geschrieben werden soll. Wenn ich das richtig sehe.

Also danke für das auf die Sprünge helfen. Manchmal steh ich ein bischen auf der Leitung. :oops: