【问题标题】:Best way to read/parse a untyped binary file in Delphi在 Delphi 中读取/解析无类型二进制文件的最佳方法
【发布时间】:2010-11-30 01:22:55
【问题描述】:

我想知道解析无类型二进制文件的最佳方法是什么。例如,EBML 文件。 (http://ebml.sourceforge.net/)。 EBML 基本上是一个二进制 xml 文件。它基本上可以存储任何东西,但它目前的主要用途是 MKV 视频文件 (matroska)。

要在字节级别读取 EBML 文件,请读取标头以确保它是 EBML 文件并检索有关文件的信息。 MKV 文件可能很大,大小为 1-30gb。

二进制文件可以是任何东西,jpeg、bmp、avi 等... 我只是想学习如何阅读它们。

【问题讨论】:

  • 非常模糊的问题。但我的回答可能会有所帮助。
  • 嗯,我想在深入了解 EBML 格式之前打下基础。感觉 EBML 与大多数其他文件类型不同,感觉它基本上是 xml。我查看了其他组件以供参考,例如 Delphi 中的 Gif 和 Png 支持。
  • 这里的例子展示了如何读取一个块,而不是单个字节......虽然我这样做是相当新的,但是对于 EBML 格式,它们使用可变大小的整数,它可能已经结束了此时我的头=)
  • 要处理单个字节,@Logman,只需读取大小为 1 的块。
  • 在不使用缓冲技术的情况下每次读取 1 个字节可能会非常慢。确实,操作系统会缓冲一些东西,但取决于要读取的数据量,这还不够。通常最好在内存中加载 n 个字节,然后从内存中工作。

标签: delphi binaryfiles


【解决方案1】:

基本上是这样

const
  MAGIC_WORD = $535B;

type
  TMyFileTypeHeader = packed record
    MagicWord: word; // = MAGIC_WORD
    Size: cardinal;
    Version: cardinal;
    Width: cardinal;
    Height: cardinal;
    ColorDepth: cardinal;
    Title: array[0..31] of char;
  end;

procedure ReadFile(const FileName: string);
var
  f: file;
  amt: integer;
  FileHeader: TMyFileTypeHeader;
begin

  FileMode := fmOpenRead;
  AssignFile(f, FileName);

  try
    Reset(f, 1);

    BlockRead(f, FileHeader, sizeof(TMyFileTypeHeader), amt);

    if FileHeader.MagicWord <> MAGIC_WORD then
      raise Exception.Create(Format('File "%s" is not a valid XXX file.', [FileName]));

    // Read, parse, and do something

  finally
    CloseFile(f);
  end;     


end;

例如,位图文件以 BITMAPFILEHEADER 结构开头,后跟(在版本 3 中)BITMAPINFOHEADER。后面是可选的调色板项数组,然后是未压缩的 RGB 像素数据(在最简单的情况下,此处为 24 位格式):BBGGRRBBGGRRBBGGRR...

另一方面,阅读 JPG 是非常复杂的,因为 JPG 数据以一种需要大量高级数学才能理解的方式进行压缩(我认为 -- 实际上我有从未真正深入研究过 JPG 规范)。至少,对于许多现代图像文件格式来说都是如此。另一方面,BMP 是微不足道的——可能发生的“最糟糕”的事情是图像被 RLE 压缩。

解析文件的“细节”完全取决于文件格式。文件格式规范告诉开发者数据是如何以二进制形式存储的(上面,两个位图结构是Windows位图规范的一部分)。它就像一份合同,由此类文件的所有编码器/解码器签署(不是字面意思)。对于 EBML,规范似乎可用here

【讨论】:

  • BlockRead 是旧的 TP 方式来读取文件。恕我直言,这是一种过时的、已弃用的技术。使用流,它是一个更通用的接口,可以利用不同的访问方法(缓冲流、内存映射等,只要您已经或已经编写了实现它们的类)具有一致的接口。
  • @Idsandon:嗯,但它工作得很好(我已经为各种各样的二进制文件类型编写了很多编码器/解码器)。为什么要放弃一个工作系统?
【解决方案2】:

只需使用 TFileStream,就像这样......

var MyFile: TStream;
begin
MyFile := TFileStream.Create( fmOpenRead, FileName);
try
  // Read stuff
  MyFile.ReadBuffer( MyVariable, SizeOf( MyVariable));
  // etc.
finally
  MyFile.Free
  end;

【讨论】:

  • 我建议调用 Read() 而不是 ReadBuffer() 来处理直接读取的字节数,而不必处理异常。
  • @ldsandon:但是 ReadBuffer 的优点是如果没有足够的字节可以从文件中读取,则会引发异常,因此您不必自己检查。如您所见:一个人的优势可能是另一个人的劣势。
【解决方案3】:

您可以对文件进行内存映射。然后你可以像访问内存一样访问它。见http://msdn.microsoft.com/en-us/library/aa366556(VS.85).aspx

【讨论】:

  • 我需要 delphi 代码/组件来帮助我理解这项技术
猜你喜欢
  • 2015-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
相关资源
最近更新 更多