Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将一个小的endian二进制文件转换为Delphi记录类型_Delphi - Fatal编程技术网

如何将一个小的endian二进制文件转换为Delphi记录类型

如何将一个小的endian二进制文件转换为Delphi记录类型,delphi,Delphi,在Delphi5中,有没有一种方法可以帮助将二进制文件转换为指定的记录?这个二进制文件是小端的。英特尔/AMD上的Windows也是小端的,所以不需要进行端位转换 现在,如果您可以显示特定的记录以及从何处获取二进制数据,那么回答起来就更容易了 您可以从文件中读取任何类型的记录。如果您的记录被声明为具有与二进制数据完全相同的布局,那么您可以一次读取整个记录。如果没有,则必须分别读取每个字段 通常,您可以使用从流中读取记录或记录的各个字段 var MyStream: TStream; ...

在Delphi5中,有没有一种方法可以帮助将二进制文件转换为指定的记录?这个二进制文件是小端的。

英特尔/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;  

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流简单地读取或写入它们。你想要的每一个布局都是可能的。回读意味着您首先读取数字,然后为其分配空间,然后在循环中读取每个项目或一次读取所有项目。如何做到这一点取决于布局。只需显示要放入文件中的记录和类型。有许多方法可以在网络字节顺序和主机字节顺序之间进行转换。但是,除非你能提出一个具体的问题,否则你不会得到具体的建议