PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : string in einer datei suchen und auslesen?


beZz_sAl
16.05.2002, 20:07
hi,

ich hab da mal folgendes problem.
ich möchte gerne aus der quake3 config den spieler name rauslesen. ich hatte das schon per offset versucht, doch allerdings kann die datei ja unterschiedlich groß sein und so würde ja, wenn(wie bei meinem kollegen) nicht der richtige string ausgelesen werden, da der offset ja nicht mehr zutrifft. nun steh ich da und hab keine ahunug wie ich das machen soll. ich hab den tipp bekommen, das ich doch mal die SmartPos, von der FastStrings.pas, function nutzensoll, doch damit komm ich nich wirklich klar.

ich danke alle die mir helfen können.


Felix Kaiser
16.05.2002, 20:19
Diese Routine kenne ich nicht ...

Ist die Datei eine Textdatei? Wenn ja wärs ja einfach. Öffne die Textdatei mit AssignFile (Typ: textfile) und Reset und lies Zeile für Zeile mit Readln Zeile für Zeile ein. Die Funktion Eof sagt dir wenn du am Ende der Datei bist. Mit UpperCase kannst du die ausgelesenen Zeilen in Großbuchstaben umwandeln, was dann die Suche nach etwas vereinfacht. Mit der Funktion Pos kannst du nun prüfen ob in der aktuellen Zeile etwas bestimmtes vorkommt. Die Parameterbeschreibungen und Beispiele für die genannten Funktionen findest du in der Hilfe.

Good luck!

beZz_sAl
16.05.2002, 20:23
das ist eine config-file.

allerdings hab ich nicht vor die ganze datei einzulesen, ich suchen ja nur einen bestimmt eintrag in der datei, geht das nicht auch ohne gleich die ganze datei einlesen zu müssen?

Felix Kaiser
16.05.2002, 20:25
Wenn du nicht zumindest bis zu der Stelle liest wo der zu suchende Eintrag ist, hast du nicht verstanden was Dateien eigentlich sind :)

Alles muss man ja nicht, kannst ja abbrechen wenn du die Zeile gefunden hast und die Datei wieder schließen.

beZz_sAl
16.05.2002, 20:35
ich kann doch sicherlich den inhalt der datei auch in einer var speicher, oder?

doch wie bekommen ich mein programm das zu das es an der richtigen stelle anhält?

ich hatte mir das so gedacht, da ich den username nich kenne, und in der datei ein anderer eintrag vor dem username steht, wollte ich erstmal bis zu dem davor stehenden eintrag suchen lassen. dann wollte ich 11 zeichen nach rechts gehen bis zu einem " und den namen solange lesen bis wieder " kommt, den username wollte ich in einem array of char speichern.

Felix Kaiser
17.05.2002, 01:48
Lassen wir das mal lieber die vorgefertigten Komponenten machen ;)

Definiere ein Variable des Objekttyps TStringList. Inizialisiere das Objekt (MeineStringListe:= TStringList.Create;). Die Stringlistenobjekte bieten Support für externe Textdateien. So kannst du auch welche in diese laden lassen.

MeineStringListe.LoadFromFile(´C:\QuellDatei.txt´);

Am besten du definierst jetzt eine for Schleife, Startindex ist 1, Endindex ist MeineStringListe.Count. Nun indizierst du jede Zeile aus der Stringliste und suchst in ihr nach dem was du suchst. Kannst auch gleich bei einem Treffer die Zeile verarbeiten und aus der Schleife rausgehn. UpperCase dient um Groß/Kleinschreibung zu umgehen.

(i = integer)


for i:= 1 to MeineStringListe.Count do
if Pos(&acute;DAS WAS ICH SUCHE&acute;,UpperCase(MeineStringListe[i-1])) <> 0 then begin
{ Treffer, MeineStringListe[i-1] ist die Zeile mit dem was du suchst, arbeite damit hier. }
break; // Aus der Schleife rausgehen, da Treffer, fertig.
end;


Alles klar?

beZz_sAl
18.05.2002, 00:34
hey guru,

ich kann mit deiner beschreibung nicht wirklich viel anfangen. ich poste mal ein teil von meinem code, vieleicht kannste mir da weiter helfen. ich bin schon so weit gekommen das ich die position ermitteln kann, nur ab dann weiß ich nich weiter:

procedure TForm1.Button1Click(Sender: TObject);
var
datei :TextFile;
dateiname :String;
inhalt :String;
posi :integer;
uname :string;
begin
dateiname:= (&acute;\baseq3\q3config.cfg&acute;);
AssignFile(datei, woisq+dateiname);
reset(datei);
while not eof(datei)do
begin
Read(datei, inhalt);
posi:= pos(&acute;seta name&acute;, inhalt);

Edit1.Text:= IntToStr(posi); {ist nur ne kleine hilfe für, um zu sehn ob
überhaupt was angezeigt wird}
end;
end;

die woisq function ermittel aus der reg den pfad der datei.

Felix Kaiser
18.05.2002, 14:29
Du hast mir noch nicht verraten was du mit dem String nach dem du ihn gefunden hast machen willst :)

Übrigens, nimm besser Readln anstatt Read!

DerWolf
18.05.2002, 15:06
Hier die Lösung mit dem Vorschlag von Guru :)
function TForm1.GetName(f: string): string;
var b: TStringList;
i, j: Integer;
name: String;
begin
result := &acute;&acute;;
b := TStringList.Create;
b.LoadFromFile(f);
for i:= 1 to b.Count do
if Pos(&acute;seta name&acute;, b[i-1]) > 0 then begin
name := &acute;&acute;;
for j := Pos(&acute;&quot;&acute;, b[i-1])+1 to Length(b[i-1])-1 do
name := name + b[i-1][j];
result := name;
break; // Aus der Schleife rausgehen, da Treffer, fertig.
end;
end;Is zwar net recht gut programmiert, aber kann in der zeit von paar minuten net besser machen ;)

Felix Kaiser
18.05.2002, 17:51
Jo, so ungefähr, nur solltest du die Stringliste auch mit Destroy wieder freigeben ;)

beZz_sAl
19.05.2002, 00:03
hey guru dein erster lösungsvorschlag hat geklappt, hab mich damit etwas länger befast und es klapt wunderbar.

ein großes thx an dich :D

Mackhack
29.05.2002, 19:15
Hi,

ist zwar schon ne weile her aber ich will dir mal meinen Code noch zur verfügung stellen:


Var
Form1: TForm1;
Quitting : Boolean = False;
Verzeichnissuche:Boolean;
implementation

{$R *.DFM}

Procedure TForm1.Button1Click(Sender: TObject);
Begin
If Opendialog1.Execute Then
Edit1.Text:= Opendialog1.Filename;
End;

Function Normal(Ch:Char) : Boolean;
Var
I : Integer;
Begin
Result:=False;
For I:= 1 To Length(Form1.Edit3.Text) Do
If Ch = Form1.Edit3.Text[I] Then
Begin
Result:=True;
Break;
End;
End;

Procedure Quit;
Begin
Form1.Close;
Halt;
End;

Procedure ScrollListBox;
Begin
With Form1 Do
Begin
If Listbox1.Items.Count > 0 Then
ListBox1.Selected[Listbox1.Items.Count-2]:= False;
ListBox1.Selected[Listbox1.Items.Count-1]:=True;
End;
End;

Function FileOk(S:String) : Boolean;
Var
F : File;
Begin
AssignFile(F,S);
{$I-}
Reset(F,1);
{$I+}
Result:= IOResult = 0;
If Result Then CloseFile(F);
End;

Procedure SuchInFile(SFile:String);
Var
F : File;
Ch : Char;
S : String;
NumRead,Pos : Integer;
Begin
If Not FileOk(SFile) Then
Exit;
With Form1 Do
Begin
Form1.Canvas.Rectangle(Label5.Left+Label5.Width,Label5.Top,Form1.Width,Form1.Height);
Form1.Canvas.TextOut(Label5.Left+Label5.Width,Label5.Top,SFile);
AssignFile(F,SFile);
Reset(F,1);
S:='';
Pos:=0;
Form1.Canvas.Brush.Color:=Form1.Color;
Repeat
If FileSize(F) > 0 {sonst div durch Null und das währe gar nicht gut :-) } Then
Begin
Form1.Canvas.TextOut(24,248, IntToStr(Round((100*Pos)/FileSize(F)))+' % ');
Form1.ProgressBar1.Position:= Round((100*Pos)/FileSize(F));
End;
Inc(Pos);
BlockRead(F,Ch,1,NumRead);
If NumRead = 0 Then
Begin
Break;
End;
If Pos = FileSize(F)-1 Then
Begin
Break;
End;
If Not Normal(Ch) Then
Begin
If Length(S) >= StrToInt(Edit2.Text) then
Begin
If Allgemein.Checked then
Begin
ListBox1.Items.Add(S);
ScrollListBox;
End
Else
If (S = Edit3.Text) Then
Begin
If (ListBox1.Items.Count <= 0) or ((ListBox1.Items.Count > 0) and (ListBox1.Items[ListBox1.Items.Count-1] <> SFile)) Then
Begin
ListBox1.Items.Add(SFile);
ScrollListBox;
End;
End;
ListBox2.Items.Add(IntToStr(Pos));
End;
S:='';
End
Else S:=S+Ch;
Application.ProcessMessages;
Until (NumRead = 0) or Quitting;
CloseFile(F);
End;
End;

Procedure TForm1.Button2Click(Sender: TObject);
Begin
If Not FileExists(Edit1.Text) Then
Begin
ShowMessage('Datei nicht vorhanden!');
Edit1.SetFocus;
Exit;
End;
Animate1.Active:=True;
Verzeichnissuche:=False;
Quitting:= False;
ListBox1.Clear;
ListBox2.Clear;
SuchInFile(Edit1.Text);
Animate1.Active:=False;
End;

Procedure TForm1.ListBox1Click(Sender: TObject);
Var
F : File;
Buf : Array[1..1000] of Char;
S : integer;
Begin
If Verzeichnissuche Then
Begin
Exit;
End;
AssignFile(F,Edit1.Text);
Reset(F,1);
Seek(F, StrToInt(ListBox2.Items[ListBox1.Itemindex]));
S:=SizeOf(Buf);
If StrToInt(ListBox2.Items[ListBox1.Itemindex])+SizeOf(Buf) > FileSize(F) then
Begin
S:= FileSize(F) - StrToInt(ListBox2.Items[ListBox1.Itemindex]);
End;
BlockRead(F,Buf,S);
CloseFile(F);
Memo1.Clear;
Memo1.Lines.Add(Buf);
End;

Procedure TForm1.Button3Click(Sender: TObject);
Var
I : Integer;
F : TextFile;
Begin
AssignFile(F, 'ListSave.txt');
ReWrite(F);
For I:= 0 To ListBox1.Items.Count-1 Do
Begin
WriteLn(F,ListBox1.Items[I]);
CloseFile(F);
ShowMessage('List saved.');
End;
End;

Procedure TForm1.BitBtn1Click(Sender: TObject);
Begin
Animate1.Active:=False;
Quitting:=True;
End;

Procedure Suche(SuchDir,TargetF:String);
Function XSuche(Dir,TargetFile:String) : String;
Var
SR : TSearchRec;
Found : Integer;

Function Directory(X:String):Boolean;
Var
I : Integer;
Begin
Result:= True;
For I:= 1 To Length(X) Do
If X[I] = '.' Then
Begin
Result:=False;
Break;
End;
End;

Begin
Found:=FindFirst(Dir+'*.*',faAnyFile,SR);
While (Found = 0) And Not Quitting Do
Begin
Application.ProcessMessages;
{ '*.EXE' }
If (TargetFile[1] = '*') And (TargetFile[3] <> '*') Then
Begin
If '*.'+StrUpper(PChar(Copy(Sr.Name,Length(Sr.Name)-2,3))) = StrUpper(PChar(TargetFile)) Then
SuchInFile(Dir+Sr.Name);
End
Else
{ '*.*' }
If (TargetFile[1] = '*') And (TargetFile[3] = '*') Then
Begin
SuchInFile(Dir+Sr.Name);
End;
If (SR.Name<>'.') And (SR.Name<>'..') And Not Quitting Then
If Directory(Sr.Name) Then
Begin
XSuche(Dir+Sr.Name+'\',TargetFile);
End;
If Not Quitting Then
Begin
Found:=FindNext(SR);
End;
End;
FindClose(Sr);
End;

Begin
If SuchDir[Length(SuchDir)] <> '\' Then
SuchDir:= SuchDir + '\';
XSuche(SuchDir,TargetF);
End;

Procedure TForm1.Button4Click(Sender: TObject);
Begin
If Not DirectoryExists(Edit4.Text) Then
Begin
Showmessage('Verzeichnis nicht vorhanden!');
Edit4.SetFocus;
Exit;
End;
Animate1.Active:=True;
Verzeichnissuche:=True;
Quitting:= False;
ListBox1.Clear;
ListBox2.Clear;
Suche(Edit4.Text, Edit6.Text);
Animate1.Active:=False;
End;

Procedure TForm1.FormActivate(Sender: TObject);
Begin
Form1.Canvas.Brush.Color:=Form1.Color;
Form1.Canvas.pen.Color:=Form1.Color;
End;

Procedure TForm1.FormKeyDown(Sender: TObject; Var Key: Word;
Shift: TShiftState);
Begin
If Key = 27 Then
Form1.Close;
End;

Procedure TForm1.BitBtn2Click(Sender: TObject);
Begin
Form1.Close;
End;

Procedure TForm1.Edit3KeyDown(Sender: TObject; Var Key: Word;
Shift: TShiftState);
Begin
Edit2.Text:= IntToStr(Length(Edit3.Text));
End;

Procedure TForm1.Edit3Exit(Sender: TObject);
Begin
Edit2.Text:= IntToStr(Length(Edit3.Text));
End;

End.

Cluni
12.01.2004, 13:38
Original geschrieben von Felix Kaiser
Jo, so ungefähr, nur solltest du die Stringliste auch mit Destroy wieder freigeben ;)
Sollte man das nicht lieber immer mit Free statt mit Destroy machen? Bei Free wird Destroy automatisch ausgeführt, aber man erhält keinen Fehler, wenn das Objekt aus irgendeinem Grund nicht mehr existiert...