这个问题非常基础,因为我处于一个非常基本的层面。我必须阅读带有*.pam
扩展名的文件的内容。它并不常见,它是由特定程序生成的文件,它具有固定大小的xx KB。里面有一些数字和值。
我需要阅读此文件,因此我将使用TStreamReader
。当然我需要知道文件的结构,但我不知道。顺便说一下,我上面的图片是一个包含有用信息的表格的一部分:
含义如下:一旦打开文件,转到特定地址并获取数据。例如,在0x30中,我可以找到关于' Move 1 Current PP'的数据。我的问题是:我如何跳转到给定的地址?
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;
我在文档中看到有类似Seek
和Position
的内容,但似乎我无法使用它们。一般来说我会用
while not(sw.EndOfStream) do
begin
//read...
end;
这从头开始,它以seqence读取数据。如何跳转到特定地址并阅读内容?我想我可以将十六进制地址传递给像Seek这样的函数,所以我可以去一个特定的点。然后我就可以检索数据了。
答案 0 :(得分:5)
如果文件内容是二进制文件(与文本文件相反),请不要使用任何文本编码选项。
在以下示例中,我使用TFileStream
来处理文件并读取文件的选定部分。 procedure ReadBuffer()
方法具有重载,它接受无类型缓冲区或类型为TBytes
的缓冲区。如果无法读取请求的字节数,它会引发EReadError
异常。
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;
与上面的代码一样,您使用Seek()
方法跳转到文件中的给定位置。读取(或写入)时位置会自动更新。 SeekOptions
是soFromBeginning
,soFromCurrent
和soFromEnd
。
有关其他详细信息,请参阅System.Classes.TFileStream。