在Delphi中读取/解析非类型二进制文件的最佳方法

在Delphi中读取/解析非类型二进制文件的最佳方法,delphi,binaryfiles,Delphi,Binaryfiles,我想知道解析非类型二进制文件的最佳方法是什么。例如,一个EBML文件。(http://ebml.sourceforge.net/). EBML基本上是一个二进制xml文件。它基本上可以存储任何东西,但目前它的主要用途是MKV视频文件(matroska) 要在字节级别读取EBML文件,请读取标头以确保它是EBML文件并检索有关该文件的信息。MKV文件可能很大,大小为1-30gb 二进制文件可以是任何东西,jpeg、bmp、avi等。。。 我只是想学习如何阅读它们 基本上是这样的 const M

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

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

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

基本上是这样的

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;
const
魔幻世界=5350亿美元;
类型
TMyFileTypeHeader=打包记录
MagicWord:word;//=神奇的单词
大小:基数;
版本:红衣主教;
宽度:基数;
身高:基数;
颜色深度:基数;
标题:字符的数组[0..31];
结束;
过程读取文件(常量文件名:字符串);
变量
f:文件;
金额:整数;
FileHeader:TMyFileTypeHeader;
开始
FileMode:=fmOpenRead;
赋值文件(f,文件名);
尝试
复位(f,1);
区块读取(f、文件头、sizeof(TMyFileTypeHeader)、金额);
如果是FileHeader.MagicWord MAGIC_单词,则
引发异常。创建(格式('文件“%s”不是有效的XXX文件',[FileName]);
//阅读、解析并做一些事情
最后
关闭文件(f);
结束;
结束;
例如,位图文件以结构开头,然后(在版本3中)是一个。后跟调色板项的可选数组,后跟未压缩的RGB像素数据(在最简单的情况下,这里是24位格式):BBGGRRBBGGRRBBGGRR

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


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

只需使用TFileStream,如下所示

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

您可以对文件进行内存映射。然后,您可以像访问内存一样访问它。见

非常模糊的问题。但我的答案可能是辅助。嗯,我想在我更深入地使用EBML格式之前先建立一个基础。Sense EBML不同于大多数其他文件类型,它基本上是xml。我已经查看了其他组件以供参考,比如Delphi中的Gif和Png支持。。。虽然我还不太熟悉这种方法,但是对于EBML格式,他们使用可变大小的整数,现在我可能不太清楚如何处理单个字节,@Logman,只读取大小为1的块。如果不使用缓冲技术,每次读取1个字节可能会非常慢。的确,操作系统会缓冲一些东西,但这取决于要读取的数据量是不够的。通常最好在内存中加载n个字节,然后从内存工作。BlockRead是以这种方式读取文件的旧TP方法。我觉得这是一种过时的、不受欢迎的技术。使用流,它是一个更通用的接口,可以利用不同的访问方法(缓冲流、内存映射等,只要您已经或已经编写了实现它们的类)和一致的接口。@Idsandon:好的,但它工作得很好(我已经为各种二进制文件类型编写了很多编码器/解码器)。为什么要放弃一个工作系统?我建议调用Read()而不是ReadBuffer()直接处理读取的字节数,而不必处理异常。@ldsandon:但ReadBuffer的优点是,如果无法从文件中读取足够的字节,则会引发异常,因此您无需亲自检查。如您所见:一个人的优势可能是另一个人的劣势。我需要delphi代码/组件来帮助我理解这个技巧