如何将一个小的endian二进制文件转换为Delphi记录类型
在Delphi5中,有没有一种方法可以帮助将二进制文件转换为指定的记录?这个二进制文件是小端的。英特尔/AMD上的Windows也是小端的,所以不需要进行端位转换 现在,如果您可以显示特定的记录以及从何处获取二进制数据,那么回答起来就更容易了 您可以从文件中读取任何类型的记录。如果您的记录被声明为具有与二进制数据完全相同的布局,那么您可以一次读取整个记录。如果没有,则必须分别读取每个字段 通常,您可以使用从流中读取记录或记录的各个字段如何将一个小的endian二进制文件转换为Delphi记录类型,delphi,Delphi,在Delphi5中,有没有一种方法可以帮助将二进制文件转换为指定的记录?这个二进制文件是小端的。英特尔/AMD上的Windows也是小端的,所以不需要进行端位转换 现在,如果您可以显示特定的记录以及从何处获取二进制数据,那么回答起来就更容易了 您可以从文件中读取任何类型的记录。如果您的记录被声明为具有与二进制数据完全相同的布局,那么您可以一次读取整个记录。如果没有,则必须分别读取每个字段 通常,您可以使用从流中读取记录或记录的各个字段 var MyStream: TStream; ...
var
MyStream: TStream;
...
MyStream := TFileStream.Create(Filename, options);
...
MyStream.Read(variable, sizeof(variable));
例如,如果您的数据来自TCP套接字,您可以将其作为字节写入TMemoryStream。然后,您可以将流的指针重置为开始并读取数据,如图所示
更新
正如David所评论的,如果字节以网络字节顺序通过TCP连接,那么在所有上述操作之后,但在使用记录中的项之前,通过WinSock函数ntohs()或ntohl()之一运行每个字段是有意义的。ntohs()转换2个字节类型,而ntohl()转换4个字节类型。要发送项目,请在发送之前(分别)对记录中的每个项目使用反向函数htons()和htonl()
FWIW,在Win32中,使用以下命令更改endianness非常容易:
// byte swaps 32 bit values
function BSwap32(I: DWORD): DWORD; { inline; }
asm
BSWAP EAX
end;
// byte swaps 16 bit values
function BSwap16(I: WORD): WORD; { inline; }
asm
XCHG AL,AH
end;
// byte swaps 64 bit values
function BSwap64(I: QWORD): QWORD; { inline; }
asm
MOV EDX,[EAX]
MOV EAX,[EAX+4]
BSWAP EAX
BSWAP EDX
end;
Intel/AMD上的Windows也是小端,因此不需要端度转换 现在,如果您可以显示特定的记录以及从何处获取二进制数据,那么回答起来就更容易了 您可以从文件中读取任何类型的记录。如果您的记录被声明为具有与二进制数据完全相同的布局,那么您可以一次读取整个记录。如果没有,则必须分别读取每个字段 通常,您可以使用从流中读取记录或记录的各个字段
var
MyStream: TStream;
...
MyStream := TFileStream.Create(Filename, options);
...
MyStream.Read(variable, sizeof(variable));
例如,如果您的数据来自TCP套接字,您可以将其作为字节写入TMemoryStream。然后,您可以将流的指针重置为开始并读取数据,如图所示
更新
正如David所评论的,如果字节以网络字节顺序通过TCP连接,那么在所有上述操作之后,但在使用记录中的项之前,通过WinSock函数ntohs()或ntohl()之一运行每个字段是有意义的。ntohs()转换2个字节类型,而ntohl()转换4个字节类型。要发送项目,请在发送之前(分别)对记录中的每个项目使用反向函数htons()和htonl()
FWIW,在Win32中,使用以下命令更改endianness非常容易:
// byte swaps 32 bit values
function BSwap32(I: DWORD): DWORD; { inline; }
asm
BSWAP EAX
end;
// byte swaps 16 bit values
function BSwap16(I: WORD): WORD; { inline; }
asm
XCHG AL,AH
end;
// byte swaps 64 bit values
function BSwap64(I: QWORD): QWORD; { inline; }
asm
MOV EDX,[EAX]
MOV EAX,[EAX+4]
BSWAP EAX
BSWAP EDX
end;
是的,我意识到Windows是little endian。我只是想知道Delphi5是否能正确处理它。我需要试一试。此外,我的数据来自TCP套接字,需要将其解码为字节数组吗?或者只是字符数组就足够了?如果您知道数据的确切声明并向我们显示记录,Delphi5可以正确处理它。这决定了它是否会起作用。如果数据已打包,而您的记录未打包,或者反之亦然,则必须分别读取每个字段。否则,您可以一次读取整个记录(假设它被正确声明)。这完全取决于file.FWIW中数据的布局,显示数据,如果记录之外有重复字段(组),则显示位置。要让人们回答你的问题,你应该给他们更多的信息。显示数据。@rudy如果数据来自套接字,它应该是网络字节顺序,因此需要转换为主机字节顺序。我想这可能就是问题背后的原因。否定。Windows不是小端机,80x86平台是。为了联网,标准套接字确实提供了网络到主机的转换例程,反之亦然。是的,我意识到Windows是little endian。我只是想知道Delphi5是否能正确处理它。我需要试一试。此外,我的数据来自TCP套接字,需要将其解码为字节数组吗?或者只是字符数组就足够了?如果您知道数据的确切声明并向我们显示记录,Delphi5可以正确处理它。这决定了它是否会起作用。如果数据已打包,而您的记录未打包,或者反之亦然,则必须分别读取每个字段。否则,您可以一次读取整个记录(假设它被正确声明)。这完全取决于file.FWIW中数据的布局,显示数据,如果记录之外有重复字段(组),则显示位置。要让人们回答你的问题,你应该给他们更多的信息。显示数据。@rudy如果数据来自套接字,它应该是网络字节顺序,因此需要转换为主机字节顺序。我想这可能就是问题背后的原因。否定。Windows不是小端机,80x86平台是。出于联网目的,标准套接字确实提供了网络到主机的转换例程,反之亦然。还有一个问题,在我的数据末尾,它是由动态长度组成的,它们是否也可以复制到记录中?比如说,将有一个标志指示有多少组将被重复,并且每个组都有一个固定的大小,类似这样的…是的,Delphi5可以处理任何你给它的东西。因此,可以通过Delphi XE2实现Turbo Pascal的任何变体。除了简单的字节顺序外,还有许多问题需要注意。例如:打包与未打包。或Pascal字符串vs C字符串vs固定长度字符数组。EtcIf您需要重复的项目,然后使用g流简单地读取或写入它们。你想要的每一个布局都是可能的。回读意味着您首先读取数字,然后为其分配空间,然后在循环中读取每个项目或一次读取所有项目。如何做到这一点取决于布局。只需显示要放入文件中的记录和类型。有许多方法可以在网络字节顺序和主机字节顺序之间进行转换。但是,除非你能提出一个具体的问题,否则你不会得到具体的建议