如何转换Big Endian以及如何翻转最高位?

时间:2010-05-21 13:27:40

标签: delphi

我正在使用TStream来读取二进制数据(感谢这篇文章:How to use a TFileStream to read 2D matrices into dynamic array?)。

我的下一个问题是数据是Big Endian。从我的阅读来看,Swap()方法似乎已被弃用。我如何交换下面的类型?

 16-bit two's complement binary integer
 32-bit two's complement binary integer
 64-bit two's complement binary integer
 IEEE single precision floating-point - Are IEEE affected by Big Endian?

最后,由于数据是无符号的,因此该数据集的创建者已将无符号值存储为有符号整数(不包括IEEE)。他们指示只需要添加一个偏移量(2 ^ 15,2 ^ 31和2 ^ 63)来恢复无符号数据。但是,他们注意到,翻转最重要的位是最快的方法。如何有效地翻转16,32或64位整数的最高位?

因此,如果磁盘上的数据(16位)为“85 FB” - 读取数据后所需的结果以及交换和位翻转将为1531.

有没有办法通过泛型实现交换和位翻转,以便它符合上面链接中的通用答案?

是的,小孩,这是NASA,ESO和所有专业天文学家存储科学天文数据的方式。这个FITS标准被一些人认为是其扩散和灵活性中最成功的标准之一!

2 个答案:

答案 0 :(得分:7)

未经测试:

function Flip16(const Value: Word): Word; inline;
begin
  Result:= Value xor $8000;
end;

function Flip32(const Value: LongWord): LongWord; inline;
begin
  Result:= Value xor $80000000;
end;

function Flip64(const Value: UInt64): UInt64; inline;
begin
  Result:= Value xor $8000000000000000;
end;

function SwapBytes(Value: LongWord): Single;
type
  Bytes = packed array[0..3] of Byte;

begin
  Bytes(Result)[0]:= Bytes(Value)[3];
  Bytes(Result)[1]:= Bytes(Value)[2];
  Bytes(Result)[2]:= Bytes(Value)[1];
  Bytes(Result)[3]:= Bytes(Value)[0];
end;

已更新:如果您要优化:)

function SwapBytes(Value: LongWord): Single; register; 
asm
  BSWAP  EAX
end;

再次更新

SO中的常见做法是每个帖子一个问题 - 它通常会产生更好的答案。

1)IEEE是否受Big Endian影响?

是的,浮点值可以是Big Endians,但这并不意味着您的浮点值是Big Endians - 请查看您的文档。

2)翻转一个最重要的位 - 已经给出了答案,但由于你可能有Big Endians,你可能只需要在最低有效字节中翻转一个最重要的位,即只需x或80美元;

3)将big endian转换为little endian;

对于16位值使用Swap函数 - 很难理解为什么delphi帮助说该函数仅用于向后兼容; Remko注意到也可以使用XCHG asm指令;

对于32位值,您可以在Marco的评论中使用我的代码或代码;

对于64位值,您可以使用像这样修改Marco代码:

function Swap64(Value: UInt64): UInt64;
begin
  Result:= Swap32(LongWord(Value));
  Result:= (Result shl 32) or Swap32(LongWord(Value shr 32));
end;

4)这里可以使用泛型吗?

我认为这不是一个好主意。

答案 1 :(得分:0)

好吧,我对字节交换知之甚少,但翻转单个位很容易。使用掩码对您的值进行异或,其二进制表示为全0,除了要翻转的位为1。如果你想要最重要的位,用十六进制表示单个字节为$80,对于一个单词为$8000,你猜对了,$80000000表示双字。