Text dosyasında string arama ve dosyada kontrol etmek

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
carsoft
Üye
Mesajlar: 138
Kayıt: 01 Ağu 2014 12:27

Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen carsoft »

Mesela : herhangi bir dosya adını bir text dosyasında varmı diye kontrol edip varsa sonraki dosyaya geçmek istiyorum

Kod: Tümünü seç

FindNext(Rec)
Text dosyasını bu şekilde yükleyip dosya adını bu dosyada arıyorum ama olmuyor

Kod: Tümünü seç

function Form1.Dosya_kontrol(const fileName, searchText: string): Boolean;
var
  sl: TStringList;
  i: Integer;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(fileName);
    for i := sl.Count-1 downto 0 do
      if Pos(searchText, sl[i])<>0 then
        Result := True
        else
        Result := False;
  finally
    sl.Free;
  end;
end;

arama kodu

Kod: Tümünü seç

procedure Form1.Dosya_ara(root: String; pattern: String);
var
  SR: TSearchRec;
begin
  root := IncludeTrailingPathDelimiter(root);
  if FindFirst(root + '*.*', faAnyFile, SR) = 0 then
  try
    repeat
      if (SR.Attr and faDirectory) <> 0 then
      begin
        if (SR.Name <> '.') and (Sr.Name <> '..') then
          Dosya_ara(root + SR.Name, pattern);
      end else
      begin
        if Dosya_kontrol(yol, SR.Name) then // eger dosya adı text dosyasında varsa sonraki dosyaya geçmesi gerekirken geçmiyor
           FindNext(SR)
           else
          Form1.ListBox1.Items.Add(Root + SR.Name);
      end;
    until FindNext(SR) <> 0;
  finally
    FindClose(SR);
  end;
end;

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
begin
  Dosya_ara('C:\Program Files', '*.exe');
end;
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen SimaWB »

Kod: Tümünü seç

Dosya_kontrol(yol, SR.Name)
Buradaki "yol" nedir?

Kod: Tümünü seç

if Dosya_kontrol(yol, SR.Name)
satırına Breakpoint koyup değişkenlerin değerlerini kontrol ettiniz mi?

Kod: Tümünü seç

if FindFirst(root + '*.*', faAnyFile, SR)
ile sadece text dosyaları değil tüm dosyaları işleme aldığınızın farkında mısınız?

Dosya_kontrol fonksiyonunun 2. parametresi aranacak kelimeyi ifade ediyor sanırım. Ama siz SR.Name ile klasör içindeki dosyanın adını gönderdiğinizin farkında mısınız?

Aslında başka sıkıntılar da var gözüküyor ama adım adım gitmekte fayda var.
There's no place like 127.0.0.1
carsoft
Üye
Mesajlar: 138
Kayıt: 01 Ağu 2014 12:27

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen carsoft »

Buradaki yol text dosyasının bulunduğu yol.

yol := string;

Kod: Tümünü seç

yol := 'C:\Program Files\dosyaadlari.txt';

Kod: Tümünü seç

Dosya_kontrol(yol, SR.Name)
ile sadece text dosyaları değil tüm dosyaları işleme aldığınızın farkında mısınız?
Evet farkındayım
Kullanıcı avatarı
SimaWB
Üye
Mesajlar: 1316
Kayıt: 07 May 2009 10:42
Konum: İstanbul
İletişim:

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen SimaWB »

yol bir değişken değil de sizin yazdığınız gibi bir sabit ise ve içerisinde sadece dosya isimlerini barındırıyorsa; bence her seferinde bu dosyayı Dosya_kontrol içinde TStringList içerisinde açmanıza gerek yok. Bu işlemi sadece bir kez yapın. Dosya_ara içinde bir TStringList içine bu dosyayı açıp, orada kullanabilirsiniz.

Bu arada; sizin probleminiz Pos fonksiyonunun büyük küçük harf duyarlı olmasında olabilir mi? Yada Pos(searchText, sl) yerine Pos(sl, searchText) yazmanız gerekiyor olabilir mi? (Yapmak istediğinizi tam olarak bilmediğim için tahmin yürütüyorum)
There's no place like 127.0.0.1
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen ertank »

carsoft yazdı:Mesela : herhangi bir dosya adını bir text dosyasında varmı diye kontrol edip varsa sonraki dosyaya geçmek istiyorum

Kod: Tümünü seç

FindNext(Rec)
Text dosyasını bu şekilde yükleyip dosya adını bu dosyada arıyorum ama olmuyor

Kod: Tümünü seç

function Form1.Dosya_kontrol(const fileName, searchText: string): Boolean;
var
  sl: TStringList;
  i: Integer;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(fileName);
    for i := sl.Count-1 downto 0 do
      if Pos(searchText, sl[i])<>0 then
        Result := True
        else
        Result := False;
  finally
    sl.Free;
  end;
end;

arama kodu

Kod: Tümünü seç

procedure Form1.Dosya_ara(root: String; pattern: String);
var
  SR: TSearchRec;
begin
  root := IncludeTrailingPathDelimiter(root);
  if FindFirst(root + '*.*', faAnyFile, SR) = 0 then
  try
    repeat
      if (SR.Attr and faDirectory) <> 0 then
      begin
        if (SR.Name <> '.') and (Sr.Name <> '..') then
          Dosya_ara(root + SR.Name, pattern);
      end else
      begin
        if Dosya_kontrol(yol, SR.Name) then // eger dosya adı text dosyasında varsa sonraki dosyaya geçmesi gerekirken geçmiyor
           FindNext(SR)
           else
          Form1.ListBox1.Items.Add(Root + SR.Name);
      end;
    until FindNext(SR) <> 0;
  finally
    FindClose(SR);
  end;
end;

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
begin
  Dosya_ara('C:\Program Files', '*.exe');
end;
Merhaba,

repeat..until döngüsü sonunda zaten bir sonraki dosyaya geçme komutu var. Siz

Kod: Tümünü seç

        if Dosya_kontrol(yol, SR.Name) then // eger dosya adı text dosyasında varsa sonraki dosyaya geçmesi gerekirken geçmiyor
          Continue
        else
          Form1.ListBox1.Items.Add(Root + SR.Name);
şeklinde yazsanız bir sonraki dosya kontrolüne geçecektir.

Dosya_kontrol() fonksiyonu içinde Pos() fonksiyonu ile kontrolü aşağıdaki şekilde yapmanız işlem performansını biraz daha hızlandıracaktır.

Kod: Tümünü seç

function Form1.Dosya_kontrol(const fileName, searchText: string): Boolean;
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(fileName);
    Result := Pos(searchText, sl.Text) > 0;
  finally
    sl.Free;
  end;
end;
carsoft
Üye
Mesajlar: 138
Kayıt: 01 Ağu 2014 12:27

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen carsoft »

ertan abi senin fonksiyonu yazınca performans çok yavaşladı.

Kod: Tümünü seç

function Form1.Dosya_kontrol(const fileName, searchText: string): Boolean;
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile(fileName);
    Result := Pos(searchText, sl.Text) > 0;
  finally
    sl.Free;
  end;
end;
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: Text dosyasında string arama ve dosyada kontrol etmek

Mesaj gönderen ertank »

Eğer yavaşlık kaynağının Dosya_kontrol() fonksiyonu olduğuna emin iseniz;

1- Pos() fonksiyonu ile aşağıdaki fonksiyonları kıyaslayıp daha performanslı olanı kullanabilirsiniz.

Kod: Tümünü seç

function PosEx_Sha_Pas_2(const SubStr, S: string; Offset: Integer = 1): Integer;
Type
  PInteger =^Integer;
var
  len, lenSub: Integer;
  ch: char;
  p, pSub, pStart, pStop: pchar;
label
  Loop0, Loop4,
  TestT, Test0, Test1, Test2, Test3, Test4,
  AfterTestT, AfterTest0,
  Ret, Exit;
begin;
  pSub := pointer(SubStr);
  p := pointer(S);

  if (p = nil) or (pSub = nil) or (Offset < 1) then
  begin;
    Result := 0;
    goto Exit;
  end;

  lenSub := PLongInt(PByte(pSub) - 4)^ - 1; // <- Modified
  len := PLongInt(PByte(p) - 4)^; // <- Modified
  if (len < lenSub + Offset) or (lenSub < 0) then
  begin;
    Result := 0;
    goto Exit;
  end;

  pStop := p + len;
  p := p + lenSub;
  pSub := pSub + lenSub;
  pStart := p;
  p := p + Offset + 3;

  ch := pSub[0];
  lenSub := -lenSub;
  if p < pStop then
    goto Loop4;
  p := p - 4;
  goto Loop0;

Loop4:
  if ch = p[-4] then
    goto Test4;
  if ch = p[-3] then
    goto Test3;
  if ch = p[-2] then
    goto Test2;
  if ch = p[-1] then
    goto Test1;
Loop0:
  if ch = p[0] then
    goto Test0;
AfterTest0:
  if ch = p[1] then
    goto TestT;
AfterTestT:
  p := p + 6;
  if p < pStop then
    goto Loop4;
  p := p - 4;
  if p < pStop then
    goto Loop0;
  Result := 0;
  goto Exit;

Test3:
  p := p - 2;
Test1:
  p := p - 2;
TestT:
  len := lenSub;
  if lenSub <> 0 then
    repeat
      ;
      if (pSub[len] <> p[len + 1]) or (pSub[len + 1] <> p[len + 2]) then
        goto AfterTestT;
      len := len + 2;
    until len >= 0;
  p := p + 2;
  if p <= pStop then
    goto Ret;
  Result := 0;
  goto Exit;

Test4:
  p := p - 2;
Test2:
  p := p - 2;
Test0:
  len := lenSub;
  if lenSub <> 0 then
    repeat
      ;
      if (pSub[len] <> p[len]) or (pSub[len + 1] <> p[len + 1]) then
        goto AfterTest0;
      len := len + 2;
    until len >= 0;
  Inc(p);
Ret:
  Result := p - pStart;
Exit:
end;
Kaynak: http://fastcode.sourceforge.net/

Kod: Tümünü seç

function RPos(const aSubStr, aString : String; const aStartPos: Integer): Integer; overload;
var
  i: Integer;
  pStr: PChar;
  pSub: PChar;
begin
  pSub := Pointer(aSubStr);

  for i := aStartPos downto 1 do
  begin
    pStr := @(aString[i]);
    if (pStr^ = pSub^) then
    begin
      if CompareMem(pSub, pStr, Length(aSubStr)) then
      begin
        result := i;
        EXIT;
      end;
    end;
  end;

  result := 0;
end;


function RPos(const aSubStr, aString : String): Integer; overload;
begin
  result := RPos(aSubStr, aString, Length(aString) - Length(aSubStr) + 1);
end;
Kaynak: http://stackoverflow.com/questions/1548 ... ng-from-th


2- Dosya okuma kısmını da optimize ederek aşağıdaki fonksiyonları kullanarak dosya içinde arama yapabilirsiniz. Bu fonksiyonlar dosya ortasında aranan değeri bulur ise devamını okumadan dosyayı kapatıp sonucu geri çevirecektir.

Kod: Tümünü seç

function StringInFile(strFind, strFileName: string): boolean;
const
  BUFSIZE = 8192;
var
  fstm: TFileStream;
  numread: Longint;
  buffer: array [0..BUFSIZE-1] of char;
  szFind: array [0..255] of char;
  found: boolean;
begin
  StrPCopy(szFind, strFind);
  found := False;
  fstm := TFileStream.Create(strFileName, fmOpenRead);
  repeat
    numread := fstrm.Read(Buffer, BUFSIZE);
    if BMFind(szFind, Buffer, numread) >= 0 then
      found := True
    else if numread = BUFSIZE then // more to scan
      fstm.Position := fstmPosition - (Length(strFind)-1);
  until found or (numread < BUFSIZE);
  fstm.Free;
  Result := found;
end;

function BMFind(szSubStr, buf: PChar; iBufSize: integer): integer;
  { Returns -1 if substring not found,
  or zero-based index into buffer if substring found }
var
  iSubStrLen: integer;
  skip: array [char] of integer;
  found: boolean;
  iMaxSubStrIdx: integer;
  iSubStrIdx: integer;
  iBufIdx: integer;
  iScanSubStr: integer;
  mismatch: boolean;
  iBufScanStart: integer;
  ch: char;
begin
  { Initialisations }
  found := False;
  Result := -1;
  { Check if trivial scan for empty string }
  iSubStrLen := StrLen(szSubStr);
  if iSubStrLen = 0 then
  begin
    Result := 0;
    Exit
  end;

  iMaxSubStrIdx := iSubStrLen - 1;
  { Initialise the skip table }
  for ch := Low(skip) to High(skip) do skip[ch] := iSubStrLen;
  for iSubStrIdx := 0 to (iMaxSubStrIdx - 1) do
    skip[szSubStr[iSubStrIdx]] := iMaxSubStrIdx - iSubStrIdx;

  { Scan the buffer, starting comparisons at the end of the substring }
  iBufScanStart := iMaxSubStrIdx;
  while (not found) and (iBufScanStart < iBufSize) do
  begin
    iBufIdx := iBufScanStart;
    iScanSubStr := iMaxSubStrIdx;
    repeat
      mismatch := (szSubStr[iScanSubStr] <> buf[iBufIdx]);
      if not mismatch then
        if iScanSubStr > 0 then
        begin // more characters to scan
          Dec(iBufIdx); Dec(iScanSubStr)
        end
      else
        found := True;
    until mismatch or found;
    if found then
      Result := iBufIdx
    else
      iBufScanStart := iBufScanStart + skip[buf[iBufScanStart]];
  end;
end;
Kaynak: http://delphidabbler.com/tips/42
Cevapla