Perl:如何将大端序转换为小端序

3
这个问题已经解决了。谢谢大家^^
以下是我的问题及解决方法。
原始问题:--- 编辑于2013-05-08
我知道可以使用 C++ 来完成这个任务,代码如下:
struct {              /* File Header */
    int a;
    int b;
    short c;    
    short d;
} PPPhdr;
PPPhdr head;
fstream fst;
fst.open("file.txt", ios_base::in|ios_base::binary);
fst.read((char*)&head, sizeof(PPPhdr));
SwapInt32(&(head.a));
SwapInt32(&(head.b));
SwapShort(&(head.c));
SwapShort(&(head.d));

所以,基本上SwapInt32会执行以下操作:
0x89346512 -> 0x12653489

SwapShort将执行以下操作:

0x3487 -> 0x8734

现在我的问题是,如何用Perl实现这个?
我的方法:
open FH, "<file.txt" or die print "Cannot open file\n";
binmode FH;
read FH, $temp, 12;
($a,$b) = unpack("N2", substr($temp,0,8));
($c,$d) = unpack("n2", substr($temp,8,4));
close(FH);
print "$a\n$b\n$c\n$d\n";

1
你能展示一下输入和期望的输出是十六进制吗? - choroba
0x89346512 -> 0x12653489 --- 这是我想要做的。 - sflee
4个回答

2

你说你的数据是大端字节序,但在解包调用中使用了有符号整数模板(i)。你应该使用无符号32位大端字节序模板(N)。你可能需要阅读文档


谢谢,我已经尝试了这个: $temp = unpack("N", $temp); print $temp; 这个结果与以下代码的结果相同: $temp = unpack("i>", $temp); print $temp; 而这不是我想要的。 - sflee
一个后续问题。如何转换有符号的32位大端数字? - sflee
1
由于整数溢出的处理方式,这段代码应该可以工作:$temp -= 2**32 if $temp > (2**31-1) - Chas. Owens

2

Perl没有针对有符号的大端整数的单字符格式。使用pack 'i>'来处理这种情况。(至少需要Perl 5.10版本)


谢谢,我已经尝试过这个代码: <br>$temp = unpack("i>", $temp); <br>print $temp; <br>但是答案不是我想要的。 <br>接下来我该怎么办? - sflee

1
你需要将其打包和解压的顺序颠倒过来:
print "ok\n" if 0x12653489 == unpack 'L', pack 'N', 0x89346512;

0

我做了这件事。首先,我感知自己是大端还是小端。可以读取文件并查看标志位(例如,在TIFF文件中的字节0-1),也可以通过自己的系统来感知大小端。

  $x = pack ("S", 256); 
  $bigendian = ord(substr ($x, 0, 1));    # 1 for bigendian 0 for littleendian

一旦我有了$bigendian的值,我就使用变量进行打包和解包:

  $short = $bigendian ? "n" : "v"; 
  $long = $bigendian ? "N" : "V"; 
  ($a,$b) = unpack($long . "2", substr($temp,0,8));
  ($c,$d) = unpack($short . "2", substr($temp,8,4));

nN代表“网络”,这是一个要求使用大端字节序的标准

vV代表“Vax”,这是一个旧的DEC系统,使用小端字节序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接