Delphi:如何从TBytes中读取X位?

Delphi: how to read X bits from TBytes?

我遇到过与从 TBytes 中读取随机位数相关的问题。首先,我遵循了这个问题的建议(关于使用 ubitstream.pas 单位的答案):Handling arbitrary bit length data in Delphi? 我的例子: 二进制进给 (TBytes) = (255, 0, 0, 0, 0, 0, 6, 132, 1, 112, 128, 128, 130, 81);

  1. 我读取 8 位并得到 255 - 好的。位置是8.
  2. 我又读了 24 位并得到 0 - 好的。位置是32.
  3. 我又读了24位,得到了393216而不是6位。位置是56。

393216 是 0000 0000 0000 0110 0000 0000 0000 0000

我能理解为什么会这样,但我不知道如何截断这些额外的零位。有任何想法吗?

问题是 endianness

00000110 00000000 00000000

是393216,将三个字节取反就是

00000000 00000000 00000110 

也就是 6。

您使用的代码是小端,但您希望大端行为。您将需要更改您的代码以解决此不匹配问题。

不过,从我们在问题中看到的情况来看,您总是读取整个字节,因此您使用的代码并不复杂。您可以在字节级别进行操作。显然,您仍然需要正确地考虑字节顺序,但这并不是很有挑战性。

首先想到你的容器。如果将字节读入 32 位整数,则应使用 shr/shl 将位移动到位。 将您不想超出 32 位范围的最左边的位 shl 并不少见,然后 shr 其余 X 个位置以获得字节值(或字,或您需要的任何大小)。

var
  value: integer;
begin
  value := (Readint32FromBuffer shl 8) shr 8;
  writeln(value.tostring);
end;

在上面的代码中,我们不希望包含前 8 位,所以我们将整个内容向左移动 8 位,然后再向后移动 8 位。当它们移动容器的 "off the edge" 时,这会将位清零。

使用 SHL 和 SHR 在变量内部移动 bits/bytes。但请记住容器的大小。字(16 位)、整数(32 位)等

您也可以使用 AND 和 OR 掩码来实现某些相同的目的,尽管对于与 CPU 寄存器(32 位或 64 位)大小相同的变量,SHL 和 SHR 通常更快。