Searching a binary file for an hex pattern

Greetings,

One of the applications I'm currently trying to integrate with uses a thing called Btrieve, for which almost no support is left. I decided then to read the (if we may call it so) database BTR files into a memory stream and perform a manual search for what I need (there's an index-like structure inside and I have all the info I need to start with).

My approach is to read this binary file into a TMemoryStream (no problem here) and perform a search into it using StrPos. What happens is that if my search string has a #0, StrPos always returns nil... Any hints how to get this done ?!?! Should I search by chars or bytes ? Is this approach the best one ? Thank you for any help on this ! Using D7.

type
  TFormMain = class(TForm)
...
  private
      { Private declarations }
      Ms1, Ms2: TMemoryStream;
...
end;
...

const
  search_arg: const = #0#0#0#128#0#5;

procedure TFormMain.Ms1LoadFromFileClick(Sender: TObject);
begin
  try
    Ms1.LoadFromFile(my_file[0].name);
    HowToReturnOffsetFromStreamHere(Ms1, search_arg);  <---  ? ? ?
  except
    Showmessage('Couldn''t read the file !' + #13 + SysErrorMessage(GetLastError));
  end;
end;
FK4Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
MeldrachaunConnect With a Mentor Commented:
There's a SearchBuf function in StrUtils that does what you want:


procedure TForm1.Button1Click(Sender: TObject);
const
  DATA = 'testing' + #0 + 'one' + #0 + 'two' + #0 + 'three' + #0;

var
  stream: TStringStream;
  ms: TMemoryStream;
  p1, p2: pointer;
  x, size, gap: integer;
  locations: string;

begin
  stream := TStringStream.Create(DATA);
  ms := TMemoryStream.Create;
  try
    ms.LoadFromStream(stream);
    p1 := ms.Memory;
    locations := '';
    size := ms.Size;
    repeat
      p2 := Pointer(SearchBuf(PChar(p1), size,0,0,#0, [soDown]));
      if p2 <> nil then
      begin
        gap := integer(p2) - integer(p1) + 1;
        dec(Size, gap);
        p1 := pointer(integer(p2)+1);

        x := integer(p2) - integer(ms.Memory);
        locations := locations + IntToStr(x)+ '  ';
      end;
    until p2 = nil;
  finally
    stream.free;
    ms.free;
  end;
  ShowMessage(locations);
end;
0
 
mokuleCommented:
Hi,
StrPos is for handling null terminated strings.
So the first occurabce of #0 terminates the string and the rest is ignored.
To allow searching for #0 use Pos() function.
0
 
FK4Author Commented:
Meldrachaun, your base sample is 98% correct but fit me 100%.

The ms in yor sample does not actually load from 'stream', but from my source file, and the argument SearchString in SearchBuf is actually your DATA constant, not #0... but again, solved my problem.

Thanks,

Fernando
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.