我正在用C解析Photoshop原始的16位/通道RGB文件,并尝试保留异常数据点的日志。我需要使用16位量子或216 MB Photoshop .RAW文件对多达36个MPix图像进行非常快速的C分析。C数据文件的前4个字节包含未签名的图像宽度,即uint32_t。在Perl中,我以二进制模式读取整个文件,并提取前32位:Xres=1779105792l = 0x6a0b0000它看起来很像C日志文件:DA: Color anomalies=14177=0.229%:DA: II=1) raw PIDX=0x10000b25, XCols=[0]=0x00000b6aDec(0x00000b6a)= 2922,小型测试文件的精确X_Columns_Width。显然是intel的1972 8008 NUXI体系结构的一个例子。将0x6a0b0000转换为0x6a0b0000有多困难?交换2个字节和2个半字节就可以了。可以对8个字符进行切片并重新排列,但这是我要避免的那种难看的技巧。从文件偏移量为零的位置获取相同的32位向量,并将其解压缩为“ VAX”无符号长整数。$xres = vec($bdat, 0, 32); # vec EXPR,OFFSET,BITS$vul = unpack("V", vec($bdat, 0, 32));printf("Length (\$bdat)=%d, xres=0x%08x, Vax ulong=%ul=0x%08x\n", length($bdat), $xres, $vul, $vul);Length ($bdat) = 56712, xres=0x6a0b0000, Vax ulong=959919921l=0x39373731每个十六进制字符都被整齐。 Endian显然是错误的,它不是VAX。 “其他”是网络大端http://perldoc.perl.org/functions/pack.htmlN An unsigned long (32-bit) in "network" (big-endian) order.V An unsigned long (32-bit) in "VAX" (little-endian) order.$nul = unpack("N", vec($bdat, 0, 32)); # Network Unsigned Long 32bprintf("Xres=0x%08x, NET ulong=%ul=0x%08x\n", $xres, $nul, $nul);Xres=0x6a0b0000, NET ulong=825702201l=0x31373739$ XRES仍然以错误的顺序显示正确的十六进制。从相同位中提取的“ NETWORK”长32位uint无法识别。尝试二进制$bits = unpack("b*", vec($bdat, 0, 32));printf("bits=$bits, len=%d\n", length $bits); bits=10001100111011001110110010011100100011000000110010101100111011001001110001001100, len=80我清楚地要求32位,并得到80位。是什么赋予了?尝试4个无符号的8位字节,这些字节不能交换:for($ii = 0; $ii < 4; $ii++) { $bit_off=$ii*8; # Bit offset $uc = unpack("C", vec($bdat, $bit_off, 8)); # C An unsigned char printf("II $ii, bo $bit_off, d=%d, u=%u, x=0x%x\n", $uc,$uc, $uc);}II 0, bo 0, d=49, u=49, x=0x31II 1, bo 8, d=51, u=51, x=0x33II 2, bo 16, d=49, u=49, x=0x31II 3, bo 24, d=49, u=49, x=0x31我正在寻找十六进制0、6,a或b。正确答案中没有“ 3”或“ 1”。尝试从C文件盗版:http://cpansearch.perl.org/src/MHX/Convert-Binary-C-0.76/tests/include/include/bits/byteswap.h$x = $xres;$x= (((($x) & 0xff000000) >> 24) | ((($x) & 0x00ff0000) >> 8) | ((($x) & 0x0000ff00) << 8) | ((($x) & 0x000000ff) << 24));printf("\$xres=0x%08x -> \$x=0x%08x = %u\n", $xres, $x, $x);$xres=0x6a0b0000 -> $x=0x00000b6a = 2922有用!但是,这比将原始的,错误的十六进制数字转换为字符串以解开字符串更难看:$stupid_str = sprintf("%08x", $xres);$stupid_num = join('', reverse ($stupid_str =~ m/../g));printf("Stupid_num '%s'->0x%08x=%d\n", $stupid_num, $dec=hex $stupid_num, $dec);Stupid_num '00000b6a'->0x00000b6a=2922这就像判断Ugliest Dog比赛一样,但是我仍然宁愿维护文本版本,而不是更加恶劣的C版本。我知道在Java / Python / Go / Ruby / .....中有多种方法可以做到这一点我知道有一些命令行工具可以做到这一点。我必须弄清楚我是如何滥用VEC或Unpack的,这两个我都用了无数次。这是“大脑戏弄”方面使我发疯! EndianNess == EndianMess !!!TYVM!=================================================波罗丁感谢您的关注。我的英特尔处理器是小端。当我读回它时,它被vec切割成“正确的” big-endian网络格式。我只是尝试从读取的BINARY文件中读取VERBATIM,但效果很好:($b4 = $bdat) =~ s/^(....).*$/$1/msg; # Give me my 4 bytes back without mutilation!printf("B4='%s'=>0x%08x=<0x%08x\n", $b4, unpack("L>", $b4), unpack("L<", $b4));B4='j...' = >0x6a0b0000 = <0x00000b6a <<< THE RIGHT ANSWER!!!      如果您尝试解压“ V”,$ bdat的包装,那么您会发现它有效  那是我的第一次尝试:    $ vul = unpack(“ V”,vec($ bdat,0,32)); #UNPACK V!    printf(“ Length(\ $ bdat)=%d,xres = 0x%08x,Vax ulong =%ul = 0x%08x \ n”,        长度($ bdat),$ xres,$ vul,$ vul);    长度($ bdat)= 56712,xres = 0x6a0b0000,Vax ulong = 959919921l = 0x39373731 我已经验证了$ BDAT信息是正确格式的正确数据。它只需要重新排列。我只是使用vec()来生成1位和4位图形文件,因此它能忠实地工作,并返回我编写的确切位。它一定把我的Intel i7误认为是IBM System / 370。 I7 / 37 ???容易犯的错误。 :)我读了[令人困惑的]部分,内容是“与pack一样转换为数字...”。这就是为什么我的电话落后了。 >> unpack(“ V”,vec($ bdat“ 现在,我明白了为什么我看到这么多人按字节提取实例,以避免大哥帮忙!Data::BitStream::Vec "uses a Perl vec to store the data. The vector is accessed in 1-bit units"感谢1E6,B (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 您将vec与unpack组合在一起使事情变得混乱正确的方法很简单unpack 'V', $bdat可以按预期返回值0x00000B6A从第一个代码块中的vec($bdat, 0, 32)值可以看到,unpack 'N', $bdat等效于$xres,并且documentation for vec通过以下方式确认这一点:  如果BITS为16或更大,则将输入字符串的字节分组为大小为BITS / 8的块,并将每个组转换为数字,如pack()/ unpack()那样使用大端格式n / N线$vul = unpack("V", vec($bdat, 0, 32))这是非常错误的,因为vec($bdat, 0, 32)的十进制值为1779105792,因此您要在字符串unpack上调用"1779105792",这根本没有任何用处 (adsbygoogle = window.adsbygoogle || []).push({});
08-05 12:32