【发布时间】:2020-05-05 21:39:22
【问题描述】:
我正在读取数据流,确切地说是 64 个字节。我想从传入数据的第 480 位开始读取 16 位。不幸的是,我不知道传入的数据类型是什么,它是一堆随机字符/框。将其作为无符号短 (v) 读入,我得到了我要查找的数字,在本例中为 13。
my $satt_id = unpack("x60v1"), $msgdata); #$satt_id == 13
这导致 $satt_id == 13,即 00000000 00001101。
如果我将数据提取为 16 位(b 或 B),则字符串不会反映 13 的值,而是字节交换或反转。
my $satt_idb = unpack("x60b16", $msgdata); #satt_idb == "10110000 00000000"
my $satt_idB = unpack("x60B16", $msgdata); #satt_idB == "00001101 00000000"
为什么会这样?我想更改数据并重新发送消息,如果所有消息元素的大小相同(16 位,只需在解包时打包),这将相对容易,但有些是 6、4、2 和1 位。我应该只使用 little-endian b 然后反转吗?修改数据后将其反转回原始顺序,然后将其打包为b?
完全独立且与 perl 无关,但这在不同的实用程序中困扰着我。我只是通过交换 Enum 名称中的值而让步。它起作用了,只是当位数高于 4(16 个不同的值)时就不太可行了。
谢谢!
编辑:我猜这只是与二进制符号有关?貌似是从右边开始的?所以 $satt_idb 是正确的,如果你从右到左阅读的话。因此,为了使其更加用户友好,只需反转、更改,然后再次反转并重新打包?
EDIT2:基本上我正在尝试制作一种用户友好的方法来编辑来自数据流的消息。正如我在 cmets 中提到的,如果我想编辑从 0 到 1 的单个位(在消息中表示真/假),我不希望用户担心编辑接收到的八位字节数据,只需从真/假下拉列表中选择。
【问题讨论】:
-
为什么还要字节的二进制表示???
-
ikegami - 有没有更好的方法从流中更改/读取 2 位和 1 位“数据”?
-
您无法从流中读取位;读取是按照八位字节(8 位)完成的。
pack/unpack类似地面向八位字节。 -
好的,是的,我同意这一点。数据以八位字节流式传输。但是假设第 7 位是一个真/假枚举。将其从 0 更改为 1(假为真)的最佳方法是什么?按八位字节解包,转换为二进制,更改,转换回八位字节,然后重新打包为八位字节?
-
@BenWest 如果你要修改它,你可能想使用perldoc.perl.org/functions/vec.html