2010-05-21 56 views
4

我正在使用TStream来读取二进制数据(感谢这篇文章:How to use a TFileStream to read 2D matrices into dynamic array?)。如何转换Big Endian以及如何翻转最高位?

我的下一个问题是数据是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标准被有些人认为是它在扩散和灵活性方面创造的最成功的标准之一!

+0

...什么?你是如何得到1531而不是7b85的? – 2010-05-21 13:46:34

+0

是的,我也得到了7B 85,其中十进制是31621. – 2010-05-21 13:52:02

+0

1531 = $ 85FB xor $ 8000 – kludg 2010-05-21 14:05:52

回答

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)翻转最显著位 - 答案已经给出,但因为你可能有大Endians,你可能只需要翻转最显著位在至少显著字节,即只是xor $ 80;

3)将big endian转换为little endian;

对于16位值使用交换功能 - 很难理解为什么delphi帮助说这个函数只是为了向后兼容; Remko注意到也可以使用XCHG asm指令;

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

为64位值,你可以使用的马可像这样的代码修改:

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

4)是否有可能在这里使用泛型?

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

+0

swap(word(value))shl 16 + swap(word(value shr 16)); – 2010-05-21 14:08:42

+0

bswap eax交换DWORD,交换WORD使用xchg al,啊 – Remko 2010-05-21 14:56:52

+2

@ user246408 - 谁是'swap32'?它是在Delphi中定义的吗? – Ampere 2015-10-18 11:31:48

0

那么,我不太了解字节交换,但翻转一个位很容易。用一个二进制表示全部为0的掩码异或你的值,除了你想要翻转的位为1。如果你想得到最高有效位,以十六进制表示,单个字节为$80,对于一个单词为$8000,对于一个双字,你猜对了,$80000000

+0

而对于64位无符号? : - ) – 2010-05-21 13:49:58

+0

在32位版本的末尾添加另外8个零。 :P – 2010-05-21 13:57:18

+0

嗯,是的,似乎接受无符号的十六进制值。如果算术运作,我将在今晚进行测试。 (FPC有一个无符号的64位类型,QWORD delphi没有) – 2010-05-21 14:06:46

相关问题