如何在数据流中搜索十六进制?

5

如何高效快速地在流中搜索十六进制数?
如果流很大,如何快速搜索并返回位置?

function FindInMemStream(Stream: TMemoryStream; What: String):Integer;
var
  bufBuffer, bufBuffer2: array[0..254] of Char;
  i: Integer;
begin
  Result := 0;
  i := 0;
  FillChar(bufBuffer, 255, #0);
  FillChar(bufBuffer2, 255, #0);
  StrPCopy(@bufBuffer2, What);
  Stream.Position:=0;
  while Stream.Position <> Stream.Size do
  begin
    Stream.Read(bufBuffer[0],Length(What));
    if CompareMem(@bufBuffer,@bufBuffer2,Length(What)) then
    begin
      Result := Stream.Position-Length(What);
      Exit;
    end;
    i := i + 1;
    Stream.Seek(i,0)
  end;
end; 

我希望将函数改为搜索十六进制,这个函数效率如何?您能否给我一个高效的搜索十六进制的函数?


3
你应该重新格式化你的代码,它很难阅读。 - Sergio Tulentsev
2
如果代码没有格式化,就不高效。 - m0skit0
6
你不是在搜索十六进制数,而是在搜索字符串,也许你可以从观察Boyer-Moore搜索算法中受益。它可以让你跳过被搜索的文本,而这个算法则是逐个字符前进。 - Lieven Keersmaekers
1个回答

3

我已经从system.pas中可用的POS函数中适应了代码 :) 如果你需要查找一些十六进制,可以像这样使用:

PosHex(#$15#$AA#$04, MyStream);

function PosHex(const SubStr: AnsiString; const StrStream: TMemoryStream): Integer;
var
  SubLen, SrcLen, Len, I, J: Integer;

  C1: AnsiChar;
  Str: PAnsiChar;
begin
  SrcLen := StrStream.Size;
  SubLen := Length(SubStr);

  Result := 0;
  if (SubLen <= 0) or (SrcLen <= 0) or (SrcLen < SubLen) then Exit;

  StrStream.Position := 0;
  Str := StrStream.Memory;

  Len := SrcLen - SubLen + 1;
  C1 := SubStr[1];
  for I := 1 to Len do
  begin
    if Str[I] = C1 then
    begin
      Result := I;
      for J := 1 to SubLen-1 do
      begin
        if Str[I+J] <> SubStr[1+J] then
        begin
          Result := 0;
          break;
        end;
      end;
      if Result <> 0 then Exit;
    end;
  end;
end;


Usage:
procedure TForm3.FormCreate(Sender: TObject);
Var
  M: TMemoryStream;
  S: AnsiString;
begin
 S := 'I would like to Find This string!';

 M := TMemoryStream.Create;
 M.WriteBuffer(S[1], Length(S));

 Memo1.Lines.Add(IntToStr(PosHex('Find This', M)));

 M.Free;
end;

(+1) 建议提供一个类似于标准或“常用”的库的函数。正如后面提到的那样,它可以进行优化,但是这仍然是一个好主意;-) - umlcat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接