Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi read file at specific address

Tags:

delphi

This question is very basic because I am at a very basic level. I have to read the contents of a file with a *.pam extension. It's not common, that's a file generated by a specific program and it has a fixed size of xx KB. There are some numbers and values inside it.

I need to read this file and so I am going to use TStreamReader. Of course I need to know the structure of the file but I don't. By the way I have the picture above that is a part of a table with useful info:

enter image description here

The meaning is the following: once you've opened the file, go to a specific address and get the data. For example, in 0x30 I can find the data about 'Move 1 Current PP'. My question is: how do I jump to a given address?

procedure TForm1.Button1Click(Sender: TObject);
var sw: TStreamReader;
begin

 Memo1.Clear;    
 sw := TStreamReader.Create('C:\aaa\myfile.pam', TEncoding.UTF8);
 try

  sw.Position := 0;

 finally
  sw.Free;
 end;

I have seen in the documentation that there is something like Seek and Position but it seems that I cannot use them. In general I would use

while not(sw.EndOfStream) do
 begin
  //read...
 end;

This starts from the beginning and it reads the data in seqence. How can I jump to a specific address and read the content? I guess that I can pass the hex address to a function like Seek, so I can go to a specific point. Then I can just retrieve the data.

like image 754
Emma Rossignoli Avatar asked Aug 07 '17 13:08

Emma Rossignoli


1 Answers

If the file content is binary (as opposite to textual) do not use any kind of text encoding options.

In the following example I use TFileStream to handle the file and to read selected parts of the file. The procedure ReadBuffer() method has overloads that takes either an untyped buffer or a buffer of type TBytes. It raises an EReadError exception if requested number of bytes can not be read.

var
  fn: TFileName;
  fs: TFileStream;
  b: byte;
  bf: array[0..3] of word;
  ReadResult: integer;
begin
  fn := 'c:\tmp\MyMagicalFile.pam';
  fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
  try
    fs.Seek($28, soFromBeginning);    // move to offset $28 in the file
    fs.ReadBuffer(bf, 8);             // read 4 x 2 bytes into buffer (bf)
                                      // fs.Position is at this point at $30
    fs.ReadBuffer(b, 1);              // read one byte (at offset $30) into the buffer (b)
  finally
    fs.free;
  end;
  // use b and bf as needed
end;

As in the code above, you jump to a given position in the file by using the Seek() method. The position is automatically updated when reading (or writing). SeekOptions are soFromBeginning, soFromCurrent and soFromEnd. For other details see System.Classes.TFileStream.

like image 176
Tom Brunberg Avatar answered Oct 05 '22 13:10

Tom Brunberg