Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.25;
Скачать: CL | DM;

Вниз

Поиск строки в большом файле   Найти похожие ветки 

 
guitarist ©   (2006-12-28 20:40) [0]

Добрый вечер.
Возникла необходимость искать строку в текстовом файле, при этом текстовой файл довольно большой (больше 4 мегабайт). Загонять все в widestring, сами понимаете долго, но тогда хоть поиск будет достаточно быстрым. Поиск нужет быстрее 5 секунд. Как это посоветуете осуществить?
Спасибо


 
Dmitrij_K   (2006-12-28 20:58) [1]

см.
CreateFileMapping + MapViewOfFile


 
Anatoly Podgoretsky ©   (2006-12-28 21:18) [2]

> guitarist  (28.12.2006 20:40:00)  [0]

А у тебя, что не текстовый файл, а Юникод файл?
Кроме того 4 мб ничтожная величина, если только у тебя не винчестер серидины 80 годов, на современных винчестерах можно на расчитывать на скорость 50+ мегабайт в секунду.


 
BiN ©   (2006-12-29 10:55) [3]

Примерно так:

procedure ReplaceFileData(const OldValue, NewValue; OldSize, NewSize: Integer; const AFileName: String);
procedure ReplaceFileString(const OldValue, NewValue: String; const AFileName: String);

implementation
Uses Windows, SysUtils, Classes;

function FindFileData(hFile: THandle; Data: Pointer; DataSize: Integer; FromPos: Integer): Int64;
var
 hFileMapping: THandle;
 FileSize: Integer;
 i, j, NP, B, N: Integer;
 Buffer: Pchar;
 Sif: SYSTEM_INFO;
 MinPageSize: Integer;
begin
 GetSystemInfo(Sif);
 MinPageSize:=Sif.dwAllocationGranularity;
 Result:=-1;
 FileSize:=Windows.GetFileSize(hFile, nil);
 if (DataSize=0) or (FileSize<DataSize) then Exit;
 hFileMapping:=CreateFileMapping(hFile, nil, PAGE_READONLY, 0, 0, nil);
 Win32Check(hFileMapping<>0);
 N:=FileSize div MinPageSize;
 for i:=0 to N-2 do
 begin
   Buffer:=MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, i*MinPageSize, MinPageSize*2);
   Win32Check(Assigned(Buffer));
   try
     for j:=0 to MinPageSize*2-1 do
       if CompareMem(@(Buffer[j]), Data, DataSize) then
       begin
         Result:=i*MinPageSize+j;
         Break;
       end;
   finally
     UnmapViewOfFile(Buffer);
   end;
   if Result<>-1 then Break;
 end;
 if Result=-1 then
 begin
   B:=FileSize mod MinPageSize;
   if B>0 then
   begin
     if N>0 then
     begin
       NP:=(N-1)*MinPageSize;
       B:=MinPageSize+B;
     end
     else
       NP:=0;
     Buffer:=MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, NP, B);
     Win32Check(Assigned(Buffer));
     try
       for j:=0 to B-1 do
         if CompareMem(@(Buffer[j]), Data, DataSize) then
         begin
           Result:=NP*1024+j;
           Break
         end;
     finally
       UnmapViewOfFile(Buffer);
     end;
   end;
 end;
 CloseHandle(hFileMapping);
end;

function GetTempFile(const PathName, Prefix:string; UID:Cardinal):String;
begin
 SetLength(Result, MAX_PATH);
 FillChar(Result[1], Length(Result), 0);
 Win32Check(GetTempFileName(Pchar(PathName), Pchar(Prefix), UID, @Result[1])0<>);
 Result:=Pchar(Result);
end;

procedure ReplaceFileData(const OldValue, NewValue; OldSize, NewSize: Integer; const AFileName: String);
var
 hFile: THandle;
 TempFileName: String;
 ValPos: Integer;
 Source, Dest: TStream;
begin
 hFile:=CreateFile(Pchar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
 Win32Check(hFile<>INVALID_HANDLE_VALUE);
 Source:=TFileStream.Create(hFile);
 try
   ValPos:=FindFileData(hFile, @OldValue, OldSize, 0);
   if ValPos<>-1 then
   begin
     TempFileName:=GetTempFile(ExtractFilePath(AFileName), "pbs", 0);
     hFile:=CreateFile(Pchar(TempFileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
     Win32Check(hFile<>INVALID_HANDLE_VALUE);
     Dest:=TFileStream.Create(hFile);
     try
       Dest.Size:=ValPos;
       Source.Seek(0, soBeginning);
       Dest.Seek(0, soBeginning);
       if ValPos>0 then
         Dest.CopyFrom(Source, ValPos);
       Source.Seek(OldSize, soFromCurrent);
       if NewSize>0 then
         Dest.Write(NewValue, NewSize);
       Dest.CopyFrom(Source, Source.Size-Source.Position);
     finally
       Dest.Free;
     end;
   end
 finally
   Source.Free;
 end;
 if (ValPos<>-1) and DeleteFile(AFileName) then
   RenameFile(TempFileName, AFileName);
end;

procedure ReplaceFileString(const OldValue, NewValue: String; const AFileName: String);
begin
 if Length(OldValue)>0 then
   ReplaceFileData(OldValue[1], NewValue[1], Length(OldValue), Length(NewValue), AFileName);
end;


 
guitarist ©   (2006-12-29 18:57) [4]

Всем спасибо. Оказалось сделал какой-то левый цикл, так что все тормозило.


 
kaZaNoVa ©   (2006-12-30 02:28) [5]

как была решена проблема?


 
ors_archangel ©   (2006-12-30 06:30) [6]


> if CompareMem(@(Buffer[j]), Data, DataSize) then

лучше юзать BM-поиск:

{ БМ-поиск подстроки в строке (алгоритм Бойера-Мура). Автор: ALex2 }
function BMPos(const sub, s: string; start: integer = 1): integer;
type
 TBMTable = array[0..255] of integer;
var
 slen, len: integer;
 pos, i: integer;
 BMT: TBMTable;
begin
 len := length(sub);
 for i := 0 to 255 do
   BMT[i] := len;
 for i := len downto 1 do
   if BMT[Byte(sub[i])] = len then
     BMT[Byte(sub[i])] := len - i;
 slen := Length(s);
 pos := start + len - 1;
 while pos <= slen do
   if sub[len] <> s[pos] then
     pos := pos + BMT[Byte(s[pos])]
   else if len = 1 then begin
     result := pos;
     exit;
   end else
     for i := len - 1 downto 1 do
       if sub[i] <> s[pos - len + i] then begin
         Inc(pos);
         Break;
       end else if i = 1 then begin
         result := pos - len + 1;
         exit;
       end;
 result := 0;
end;



Страницы: 1 вся ветка

Текущий архив: 2007.02.25;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.049 c
2-1170671273
kail
2007-02-05 13:27
2007.02.25
запуск программы один раз


1-1167904951
Kolan
2007-01-04 13:02
2007.02.25
Иключения в потоке. Как правильно обрабатывать?


4-1161024235
spok
2006-10-16 22:43
2007.02.25
Процесс от имени другого юзера - как? (почему не работает?)


15-1170176379
Chort
2007-01-30 19:59
2007.02.25
Распределить текст по разным столбцам


1-1167208489
Yozch1
2006-12-27 11:34
2007.02.25
цвет хидера в VTV