Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.02.25;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.043 c
2-1170457963
acorables
2007-02-03 02:12
2007.02.25
Передача данных(массива) через DLL.


15-1170156682
TIF
2007-01-30 14:31
2007.02.25
Помогите решить задачки!


15-1170519024
hmmm
2007-02-03 19:10
2007.02.25
PHP как получить адресную строку


15-1170614636
hmmm
2007-02-04 21:43
2007.02.25
RSDN


2-1170756305
dr_craigan
2007-02-06 13:05
2007.02.25
Запрет работы устройства





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский