如何读取非类型化文件的字节头,然后在 Free Pascal 和 Lazarus 中作为文件流时使用和显示该数据

发布于 2024-10-31 23:23:40 字数 1497 浏览 3 评论 0原文

我正在尝试使用 Lazarus 学习 Free Pascal,我的一个宠物项目涉及读取一组特定的无类型文件的 64 字节标头,这些文件无法使用文本或 ASCII 相关程序读取和显示(因此无法直接输出到备注框等) )。

到目前为止,我已经设计了以下代码,我认为它读取了标头的 64 个字节,并且根据通过 Lazarus IRC 收到的建议,我使用 TStreams 和“选择目录”对话框来执行此操作。我的问题是如何实际使用从标头读入缓冲区的数据?例如,在标头中,有 8 个字节的序列,然后是 16 个字节,然后是 2 个字节等等,我想“处理”这些输出以生成其他输出,这些输出最终将转换为字符串以进入我的字符串网格。

到目前为止,我所拥有的一些内容是基于我在此处发现的由 Mason Wheeler 接近结尾处编写的内容(http://stackoverflow.com/questions/455790/fast-read-write-from-file-in-delphi),但它只展示如何读入,不展示如何使用。我也读过这篇文章(http://stackoverflow.com/questions/4309739/best-way-to-read-parse-a-untyped-binary-file-in-delphi),但它再次向您展示了如何读取数据也是如此,但随后不使用该数据。热烈欢迎任何指导!到目前为止,下面的代码仅将单值整数输出到编辑框,而不是 8 个十六进制值的范围。

PS-我是编程新手,所以请温柔一点!没什么太复杂的。

procedure TForm1.ProbeFile(FileIterator: TFileIterator);

type
 TMyHeader = Array[1..64] of packed record
 First8Bytes,
 Next16Bytes,
 Next2Bytes: byte;
 end;

var

  FI : TFileIterator;                      //File Iterator class
  SG : TStringGrid;
  NumRead : SmallInt;
  FileToProbe: TStream;
  header: TMyHeader;

begin
  FI := TFileIterator.Create;
  SG := TStringGrid.Create(self);


  // Open the file and read the header
  FileToProbe := TFileStream.Create(FileIterator.FileName, fmOpenRead);
  try
    FileToProbe.seek(0, soFromBeginning);
    FileToProbe.ReadBuffer(header, SizeOf(header));
    edit1.text := IntToStr(header[0].First8Bytes);  // Just outputs '0' to the field?  If I try '10' it ooutputs '29' and so on
  finally
    FileToProbe.Free;
  end; 

I am trying to learn Free Pascal using Lazarus and one of my pet projects involves reading the 64 byte headers of a particular set of untyped files that cannot be read and displayed using text or ASCII related procedures (so cannot be outputted directly to Memo boxes etc).

So far, I have devised the following code which does, I think, read in the 64 bytes of the header and I am using TStreams and a "Select Directory" dialog box to do this, based on advice received via the Lazarus IRC. My question though is how to actually USE the data that is read into the buffer from the header? For example, in the headers, there are sequences of 8 bytes, then 16 bytes, then 2 bytes and so on that I want to "work on" to generate other output that will eventually be converted to a string to go into my string grid.

Some of what I have so far is based on what I found here written by Mason Wheeler near the end (http://stackoverflow.com/questions/455790/fast-read-write-from-file-in-delphi) but it only shows how to read it in, not how to use it. I also read this (http://stackoverflow.com/questions/4309739/best-way-to-read-parse-a-untyped-binary-file-in-delphi) but again, it shows you how to READ the data too, but not subsequently USE the data. Any guidance wamrly received! So far, the code below just outputs single value integer numbers to the edit box, as opposed to, say, a range of 8 hexadecimal values.

PS - I am new to programming so please be gentle! Nothing too complex.

procedure TForm1.ProbeFile(FileIterator: TFileIterator);

type
 TMyHeader = Array[1..64] of packed record
 First8Bytes,
 Next16Bytes,
 Next2Bytes: byte;
 end;

var

  FI : TFileIterator;                      //File Iterator class
  SG : TStringGrid;
  NumRead : SmallInt;
  FileToProbe: TStream;
  header: TMyHeader;

begin
  FI := TFileIterator.Create;
  SG := TStringGrid.Create(self);


  // Open the file and read the header
  FileToProbe := TFileStream.Create(FileIterator.FileName, fmOpenRead);
  try
    FileToProbe.seek(0, soFromBeginning);
    FileToProbe.ReadBuffer(header, SizeOf(header));
    edit1.text := IntToStr(header[0].First8Bytes);  // Just outputs '0' to the field?  If I try '10' it ooutputs '29' and so on
  finally
    FileToProbe.Free;
  end; 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黯然#的苍凉 2024-11-07 23:23:40

如果我误解了你的问题,请原谅我。

据我了解,有一个 64 字节的标头。前 8 个字节属于在一起,然后是接下来的 16 个字节,最后是另外 2 个字节。

对我来说,这个标头的声明应该是:

   TMyHeader = packed record
     First8Bytes: array[0..7] of byte;  
     Next16Bytes: array [0..15] of byte;
     Next2Bytes: array [0..1] of byte;
     // add more if you like
   end;

这个记录类型的大小为 8+16+2 = 26 字节。

您读取标题的代码对我来说看起来不错,所以我不会重复。

可以检索标头中的 next16bytes,例如,如下所示:

edit1.text:= '';
// needs a declaration of a variable "i" as integer
for i:= 0 to 15 do
  edit1.text:= edit1.text + IntToStr(header.next16bytes[i]) + '-';

如下所示更改标头的 next2bytes 部分中第一个字节的值(再次作为示例):

header.next2bytes[0]:= 123;

最后,您可以将更改写回标头借助 filetoprobe.writebuffer 方法的文件。

Please forgive me if I misunderstood your question.

As I understand it there is a header of 64 bytes. The first 8 bytes belong together, then the next 16 bytes and finally another 2 bytes.

To me it seems the declaration for this header should be:

   TMyHeader = packed record
     First8Bytes: array[0..7] of byte;  
     Next16Bytes: array [0..15] of byte;
     Next2Bytes: array [0..1] of byte;
     // add more if you like
   end;

This recordtype has a size of 8+16+2 = 26 bytes.

Your code that reads the header looks ok to me, So I won't repeat that.

The next16bytes in your header can be retrieved, for example, like this:

edit1.text:= '';
// needs a declaration of a variable "i" as integer
for i:= 0 to 15 do
  edit1.text:= edit1.text + IntToStr(header.next16bytes[i]) + '-';

Change the value of the first byte in the next2bytes part of your header as follows (again as an example):

header.next2bytes[0]:= 123;

Finally, you could write your changes back to the header of the file with help of the filetoprobe.writebuffer method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文