如在PE文件中一段字节 ... 12 21 21 54 4F 35 1F 65 22 ...  我要搜索其中的 21 54 4F 35 1F 并让他返回地址.请问该如何处理.这是一段搜索流中字符的一段代码.请问我要改为搜索字节数组的话要怎么改function ScanStream(mStream: TStream; mStr: string): Integer;          //搜索字符窜
const
  cBufferSize          = $8000;
var
  S          : string;
  T          : string;
  I          : Integer;
  L          : Integer;
begin
  Result := -1;
  if not Assigned(mStream) then Exit;
  if mStr = '' then Exit;
  L := Length(mStr);
  mStream.Position := 0;
  SetLength(S, cBufferSize);
  T := '';
  for I := 1 to mStream.Size div cBufferSize do begin
    mStream.Read(S[1], cBufferSize);
    Result := Pos(mStr, T + S) - 1;          //保留上次搜索的尾部字符~~
    T := Copy(S, cBufferSize - L, MaxInt);
    if Result >= 0 then begin
      Result := Result + Pred(I) * cBufferSize - Length(T);
      Exit;
    end;
  end;
  I := mStream.Size mod cBufferSize;
  SetLength(S, I);
  if I > 0 then begin
    mStream.Read(S[1], I);
    Result := Pos(mStr, T + S) - 1;
    if Result >= 0 then begin
      Result := Result + mStream.Size - I - Length(T);
      Exit;
    end;
  end;
end;

解决方案 »

  1.   

    最简单的方法就是递归调用.
    function ScanStreamMuti(mStream: TStream; mStr:array of string): Integer; 
    var
      i : integer;
    begin
      Assert(Assigned(mStream));
      result := -1;
      if Length(mStr) = 0 then Exit;
        
      for i := low(mStr) to high(mStr) do begin
        result := ScanStream(mMStream, mStr[i]);
        if result>=0 then break;
      end
    end;还有你上面代码效率和处理上也有问题:1. mStream.Read(S[1], cBufferSize);  最好处理它的返回值,特别是在扩展流中屏掉了错误
        ,导致返回值为空或都小于时,这时查找会一直以S缓存中的数据(如果执行过一次的话)来查找.结果不可预料的.
    2. 
        T := Copy(S, cBufferSize - L, MaxInt); 
        if Result >= 0 then begin 
          Result := Result + Pred(I) * cBufferSize - Length(T); 
          Exit; 
        end; 
        ==>    
        if Result >= 0 then begin 
          Result := Result + Pred(I) * cBufferSize - Length(T); 
          Exit; 
        end; 
        T := Copy(S, cBufferSize - L, MaxInt); 
        在查找成功时,这句代码根本就无所用处.
    3.  
           Result := Pos(mStr, T + S) - 1;          //保留上次搜索的尾部字符~~ 
        T := Copy(S, cBufferSize - L, MaxInt); 

       如果在大文件查找时,这两句代码进行的内存COPY是有点代价的.
       既然每次都要COPY文件的保留上次搜索的尾部字符,不如在分配缓冲S时候就加上这个长度
       [Length(mStr)] + [cBufferSize]
       每次查完一次,只复制尾部到S到前面即可,减少了T + S和Copy函数又执的一次内存分配动作还有其它一些问题和算法效率,我就不说了
      

  2.   

    这个函数看上去面熟,,,是我写的如果是array of byte可以先将字节数组转换成字符串:
    var S: string;
    //vBytes: array of byte;//假设已经赋值
    begin
      SetLength(S, Length(vBytes));
      Move(vBytes[0], S[1], Length(vBytes));
      I := ScanStream(vStream, S);
    end;