Entwickler-Ecke

Sonstiges (Delphi) - .dfm Dateien Umbrüche entfernen


Sahroma - Do 28.05.15 09:06
Titel: .dfm Dateien Umbrüche entfernen
Hallo zusammen,

ich habe ein Programm geschrieben das *.dfm, *.pas und *.txt Dateien durchsucht nach Wörtern die ich in eine TEdit Box eintrage. Funktioniert auch alles ohne Probleme nur habe ich mit den *.dfm Dateien Probleme, erstens weil diese ja Umbrüche haben und Umlaute (ä,ü usw) umwaltet in z.B #230. Ich versuche schon seit mehreren Wochen dies hin zubekommen habe auch schon das Internet durchforstet aber nichts gefunden. Ihr seit jetzt meine letzte Hoffnung. :oops:
Hier mal den Code von der Suche:


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:
procedure TVolltextsuche.FindMyFiles;
var
  LFiles: TStringDynArray;
  LStrs: TStringList;
  LValue: string;
  i : Integer;
begin
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.txt',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.dfm',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.pas',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
end;

function TVolltextsuche.BuildDirectoryFilterPredicate(ASearchText: string): TDirectory.TFilterPredicate;
begin
  Result :=
    function(const Path: stringconst SearchRec: TSearchRec): Boolean
    begin
      Result := ContentContainsText(PrepareContentForSearch(GetContentFromFile(TPath.Combine(Path, SearchRec.Name))), ASearchText);
    end;
end;

function TVolltextsuche.GetContentFromFile(const AFilename: string): string;
begin
  Result := TFile.ReadAllText(AFilename);
end;

function TVolltextsuche.PrepareContentForSearch(const AContent: string): string;
begin
  Result := AContent;
end;

function TVolltextsuche.ContentContainsText(const AContent: stringconst ASearchText: string): Boolean;
begin
  Result := AContent.Contains(ASearchText);
end;


Habt ihr da Vorschläge wie ich die Umbrüche vor der Suche aus der Datei temporär entferne und das die Suche die codierten Umlaute beachtet? Danke schonmal für eure Hilfe.

Grüße
Sahroma


Stundenplan - Do 28.05.15 13:48

Warum auch immer du Umbrüche entfernen willst - StringReplace sollte treue Dienste leisten: Ersetze einfach alle #13 und alle #10 durch Leerstrings.
Genauso kannst du auch Umlaute behandeln.


Sahroma - Do 28.05.15 13:56

user profile iconStundenplan hat folgendes geschrieben Zum zitierten Posting springen:
Warum auch immer du Umbrüche entfernen willst - StringReplace sollte treue Dienste leisten: Ersetze einfach alle #13 und alle #10 durch Leerstrings.
Genauso kannst du auch Umlaute behandeln.


An StringReplace habe ich auch schon gedacht aber irgendwie krieg ich den Code nicht richtig gebacken. Warum ich Umbrüche entfernen will ist eine lange Geschichte. :) Soweit ich weiß funktioniert StringReplace doch nur mit StringList o.ä. und nicht mit normalen Strings oder StringArrays wie es bei mir der Fall ist oder habe ich da etwas falsch verstanden?

Programmiere mit Delphi noch nicht so lange, entschuldigt also gegebenenfalls dumme Fragen. :lol:


Stundenplan - Do 28.05.15 14:02

Doch, StringReplace nimmt einzelne Strings und verarbeitet diese. ;-)
Bsp.: result := StringReplace(AContent, #13'', [rfReplaceAll]);
Damit ersetzt du in AContent den Char #13 durch einen Leerstring; rfReplaceAll bestimmt, dass alle Vorkommnisse ausgetauscht werden.


Sahroma - Do 28.05.15 14:13


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
LFiles := TDirectory.GetFiles(ebPfad.Text,'*.dfm',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        LValue := StringReplace(LValue,'''+''', [rfReplaceAll]);
        LValue := StringReplace(LValue,'''''', [rfReplaceAll]);
        LValue := StringReplace(LValue,#13#10'', [rfReplaceAll]);
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;


Habe es mal so eingefügt aber wenn ich dann den Compiler starte, kommt die Meldung: "Der linken Seite kann nichts zugewiesen werden". Stelle ich mich da jetzt nur doof an?


SMO - Do 28.05.15 15:08

For-Schleifenvariablen sind in der Tat Read-Only.

Entweder so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var i: Integer;

for i := Low(LFiles) to High(LFiles) do
begin
  LValue := LFiles[i];
  LValue := StringReplace(LValue,'''+''', [rfReplaceAll]);
  // usw.
end;


oder so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var temp: string;

for LValue in LFiles do
begin
  temp := LValue;
  temp := StringReplace(temp,'''+''', [rfReplaceAll]);
  // usw. mit temp
end;


Sahroma - Do 28.05.15 15:24

Danke für die Infos. Habe die zweite Möglichkeit von SMO ausprobiert aber es will immer noch nicht so wie es sein soll. Er ignoriert den StringReplace komplett.
Hier mal den kompletten Code vom Programm mit allen Buttons usw. vielleicht findet ihr da ein Fehler was das verhindert. Ich bin mit meinem Latein komplett am Ende. :(


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:
unit Volltext;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Types, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ComCtrls, Vcl.FileCtrl, System.IOUtils,
  System.Masks, Winapi.ShellAPI, Vcl.Buttons;

type
  TVolltextsuche = class(TForm)
    lbErgebnis: TListBox;
    btnStart: TButton;
    btnLöschen: TButton;
    ebSuche: TEdit;
    btnSucheN: TButton;
    FormPanel: TPanel;
    lblSucheT: TLabel;
    lblSucheP: TLabel;
    ebPfad: TEdit;
    procedure btnSucheNClick(Sender: TObject);
    procedure btnLöschenClick(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure lbErgebnisClick(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure FindMyFiles;
    // Lädt den Inhalt aus der Datei in einen String
    function GetContentFromFile(const AFilename: string): string;
    // Überarbeitet den Content für die einfachere Suche nach dem Text
    function PrepareContentForSearch(const AContent: string): string;
    // Durchsucht den Content nach dem Suchtext
    function ContentContainsText(const AContent, ASearchText: string): Boolean;
    // Erzeugt den Such-Filter
    function BuildDirectoryFilterPredicate(ASearchText: string): TDirectory.TFilterPredicate;
  public
    { Public-Deklarationen }
  end;

var
  Volltextsuche: TVolltextsuche;
  OverrideCbBAdr: Boolean = False;
implementation

{$R *.dfm}
procedure TVolltextsuche.FindMyFiles;
var
  LFiles: TStringDynArray;
  LStrs: TStringList;
  LValue: string;
  dfmstring : string;
begin
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.txt',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.dfm',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        dfmstring := LValue;
        dfmstring := StringReplace(dfmstring,'''+''', [rfReplaceAll]);
        dfmstring := StringReplace(dfmstring,'''''', [rfReplaceAll]);
        dfmstring := StringReplace(dfmstring,#13#10'', [rfReplaceAll]);
        lbErgebnis.Items.Add(dfmstring);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.pas',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
end;

function TVolltextsuche.BuildDirectoryFilterPredicate(ASearchText: string): TDirectory.TFilterPredicate;
begin
  Result :=
    function(const Path: stringconst SearchRec: TSearchRec): Boolean
    begin
      Result := ContentContainsText(PrepareContentForSearch(GetContentFromFile(TPath.Combine(Path, SearchRec.Name))), ASearchText);
    end;
end;

function TVolltextsuche.GetContentFromFile(const AFilename: string): string;
begin
  Result := TFile.ReadAllText(AFilename);
end;

procedure TVolltextsuche.lbErgebnisClick(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to lbErgebnis.Items.Count -1 do
    begin
      if lbErgebnis.Selected[i] then
      ShellExecute(Handle, 'open', PChar('notepad'), PChar(lbErgebnis.Items.Strings[i]), nil, SW_SHOW);
    end;
end;

function TVolltextsuche.PrepareContentForSearch(const AContent: string): string;
begin
  Result := AContent;
end;

function TVolltextsuche.ContentContainsText(const AContent: stringconst ASearchText: string): Boolean;
begin
  Result := AContent.Contains(ASearchText);
end;

procedure TVolltextsuche.btnLöschenClick(Sender: TObject);
begin
lbErgebnis.Clear;
end;

procedure TVolltextsuche.btnStartClick(Sender: TObject);
begin
FindMyFiles;
end;

procedure TVolltextsuche.btnSucheNClick(Sender: TObject);
var
  Directory: string;
begin
  Directory := 'C:\';
    if SelectDirectory('Bitte ein Verzeichnis wählen. ','',Directory) then
      begin
        if not OverrideCbBAdr then
          begin
            OverrideCbBAdr := True;
            ebPfad.Text:= '';
          end;
            ebPfad.Text := Directory;
      end;
end;

end.


Stundenplan - Do 28.05.15 16:00

Momentan wendest du die Replaces ja auch auf die Dateinamen an; ich nehme an, der Replace-Code gehört in PrepareContentForSearch?


Sahroma - Fr 29.05.15 07:44

user profile iconStundenplan hat folgendes geschrieben Zum zitierten Posting springen:
Momentan wendest du die Replaces ja auch auf die Dateinamen an; ich nehme an, der Replace-Code gehört in PrepareContentForSearch?


Oh jetzt wo du es sagst, stimmt. :oops:
So kann das natürlich nicht funktionieren. Danke dir vielmals. :idea:


Sahroma - Do 11.06.15 08:57

Programm läuft nun ohne Probleme. Nun bin ich dabei noch ein paar Zusatzfunktionen einzufügen. Bisher habe ich eine EditBox wo mir die Anzahl der gefundenen Treffer anzeigt. Würde aber gerne noch eine zusätzlich Editbox einbauen wo mir die Anzahl ALLER Ergebnisse ausgibt (also wie viele Dateien er insgesamt durchsucht hat). Bekomme das aber irgendwie nicht gebacken. Könnt ihr mir da weiterhelfen?


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:
procedure TVolltextsuche.FindMyFiles;
var
  LFiles: TStringDynArray;
  LValue: string;
  Treffer: Integer;
begin
  pb1.Min := 0;
  pb1.Max := 80;
  pb1.Step := 20;
  Treffer := 0;
  pb1.StepIt;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.txt',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  pb1.StepIt;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.dfm',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  pb1.StepIt;
  LFiles := TDirectory.GetFiles(ebPfad.Text,'*.pas',TSearchOption.soAllDirectories,BuildDirectoryFilterPredicate(ebSuche.Text));
  lbErgebnis.Items.BeginUpdate;
  try
    for LValue in LFiles do
      begin
        lbErgebnis.Items.Add(LValue);
      end;
  finally
    lbErgebnis.Items.EndUpdate;
  end;
  pb1.StepIt;
  ebGTreffer.Text := IntToStr(lbErgebnis.Items.Count);
end;


ebGTreffer = Editboxname für gefundene Treffer. Eine zusätzliche Editbox soll wie bereits beschrieben noch ALLE Ergebnisse während der Suche ausgeben.


Delete - Do 11.06.15 09:47

- Nachträglich durch die Entwickler-Ecke gelöscht -


Sahroma - Do 11.06.15 10:03

user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Sahroma,

im ersten Beitrag stand doch:

Zitat:
ich habe ein Programm geschrieben das *.dfm, *.pas und *.txt Dateien durchsucht nach Wörtern die ich in eine TEdit Box eintrage [...]

und jetzt:

Zitat:
Würde aber gerne noch eine zusätzlich Editbox einbauen wo mir die Anzahl ALLER Ergebnisse ausgibt (also wie viele Dateien er insgesamt durchsucht hat) [...]

Möchtest du nun die Anzahl aller gefundenen Wörter ermitteln oder die Anzahl aller .dfm / .pas / .txt Dateien ermitteln?
Für beide Fälle müsstest du nur eine Variable definieren die bei 0 anfängt und sich um 1 erhöht, sobald ein Treffer vorhanden ist bzw. eine Datei durchsucht wurde.


Ich möchte die Anzahl ALLER .dfm / .pas / .txt Dateien wissen (nicht nur die wo mit dem Eintrag in der Editbox übereinstimmen). Sorry da habe ich mich falsch ausgedrückt. Das mit dem Wert immer um 1 erhöhen habe ich mir auch schon gedacht nur sind alle Versuche die ich damit gemacht habe fehlgeschlagen. Denke einfach das ich mich da wieder dumm anstelle und es ganz einfach ist. :oops:


baumina - Do 11.06.15 10:15

GetFiles ohne Editfeld-Suchkriterien aufrufen und gefundene Anzahl ausgeben.


Delete - Do 11.06.15 12:08

- Nachträglich durch die Entwickler-Ecke gelöscht -


Sahroma - Do 11.06.15 15:06

Danke euch beiden. Habe bauminas Variante genommen und funktioniert genau so wie ich es mir gedacht habe.


Sahroma - Fr 12.06.15 14:03

Ich weiß ich gehe euch mit meinen dummen Fragen auf die Nerven, aber leider arbeite ich mit Delphi noch nicht so lange.
Mein Suchergebnis gebe ich ja in einer ListBox aus, nun habe ich die Anweisung das ich es in ein TListView ausgebe soll. Habe damit noch überhaupt keine Erfahrung. Habe bisher 4 Spalten in die ListView Box eingefügt (Name der Datei, Ordner wo die Datei liegt, Größe der Datei und Typ (pas oder dfm oder txt). Ich habe aber absolut keine Ahnung wie ich das Suchergebnis so zerteile das die Inhalte der jeweiligen Spalten auch stimme? Bisher bekam ich nur den kompletten Pfad in der Namens Spalte ausgegeben.


Delete - Fr 12.06.15 20:52

- Nachträglich durch die Entwickler-Ecke gelöscht -


Sahroma - Fr 19.06.15 14:44

Und wieder ist ein Problem aufgetreten bzw. ich stehe auf dem Schlauch. Habe nun ein MemoFeld im Formular drin mit einer Checkbox. Wenn die Checkbox markiert ist soll bei der Suche die im Memofeld eingetragen Ordner von der Suche ausgeschlossen werden. Ich sitze hier wie in Anfänger der das erst mal programmiert. Mir fällt einfach nicht ein wie ich das umsetze. Bitte helft mir auf die Sprünge. :nixweiss:


Delete - Fr 19.06.15 17:22

- Nachträglich durch die Entwickler-Ecke gelöscht -