Текущий архив: 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.47 MB
Время: 0.041 c