dfm文件二进制格式时, 其文件会加一个文件头, 其中前3个字节来标识其为二进制, 这三个字节分别为:$FF, $0A, $00. 因为这三个字节在文本类型的文件中是不可能存在的,所以可以判断这3个字节就可以了.
function IsBinDfm(const ADfmFileName: string): Boolean;
Var
mBinStream:TMemoryStream;
mBuff : array [0..2] of byte;
begin
mBinStream := TMemoryStream.Create;
try
mBinStream.LoadFromFile(ADfmFileName);
mBinStream.Read(mBuff, 3);
//前三字节: $FF, $0A, $00
if (mBuff[0] = $FF) and (mBuff[1] = $0A) and (mBuff[2]= $00) then
Result := True
else
Result := False;
finally
mBinStream.Free;
end;
end;
实际上,DFM文件内容是二进制数据,它的脚本是经过Delphi开发环境自动转化的,而且Delphi VCL中的Classes库单元提供了在二进制流中的文件DFM和它的脚本之相互转化的过程。它们是ObjectBinaryToText和ObjectTextToBinary、ObjectResourceToText和ObjectTextToResource。
ObjectBinaryToText过程将二进制流中存储的部件转化为基于文本的表现形式,这样就可以用文本处理函数进行处理,还可以用文本编辑器进行查找和替代操作,最后可以将文本再转化成二进制流中的部件。
ObjectTextToBinary过程执行的功能与ObjectBinaryToText相反,将TXT文件转换为二进制流中的部件,而且只要TXT文件内容的书写符合DFM脚本语法,ObjectTextToBinary可将任何程序生成的TXT文件转换为部件,这一功能也为DFM文件的动态生成和编辑奠定了基础。
使用ObjectResourseToText可以将dfm文件的二进制文件转为为文本文件。
ObjectResourseToText过程比较简单,如下:
procedure ObjectResourceToText(Input,Output:TStream);
begin
Input.ReadResHeader;
ObjectBinaryToText(Input,Output);
end;
ObjectTextToResource过程就比较复杂,因为DFM文件资源头中要包含继承标志信息,因此在调用ObjectTextToBinary后,就读取标志信息,然后写入资源头。
procedure ObjectTextToResource(Input,Output:TStream);
var
Len:Byte;
Tmp:Longint;
MemoryStream:TMemoryStream;
MemorySize:Longint;
Header:array[0.79] of Char;
begin
MomoryStream:=TMemoryStream.Create;
try
ObjectTextToBinary(Input,MemoryStream);
MemorySize:=MemoryStream.Size;
FillChar(Header,SizeOF(Header),0);
MemoryStream.Position:=SizeOf(Longint);{Skip header}
MemoryStream.Read(Len,1);
if Len and $F0=$F0 then
begin
if ffChildPos in TFilerFlags(Len and $F0) then
begin
MemoryStream.Read(Len,1);
case TValueType(Len) of
vaInt8:Len:=1;
vaInt16:Len=2;
vaInt32:Len=4;
end;
MemoryStream.Read(Tmp,Len);
end;
MemoryStream.Read(Len,1);
end;
MemoryStream.Read(Header[3],Len);
StrUpper(@Header[3]);
Byte((@Header[0])^):=$FF;
Word((@Header[1])^):=10;
Word((@Header[Len+4])^):=$1030;
Longint((@Header[Len+6])^):=MemorySize;
Output.Write(Header,Len+10);
Output.Write(MemoryStream.Memory^,MemorySize);
finally
MemoryStream.Free;
end;
所以在获取一个dfm文件的内容时需要先判断一下文件的类型,是二进制还是二进制的文件,如果是二进制文件需要将其调用ObjectResourseToText方法转为非二进制文件。