从文件中读取反转字节作为十进制数

时间:2014-03-22 14:36:09

标签: perl

我正在尝试从Perl中的Civilization 2存档游戏文件中读取转弯号码。我有一个非常草率的解决方案,但必须有一个更优雅的解决方案。

它们在偏移28和29(0x1C,0X1D)处存储为两个字节。对于小于256的转弯,仅使用第一个字节(0x1C)。对于较高的转弯数,使用第二个字节。奇怪的是,它们似乎与我的期望相反。也就是说,转向300存储为0x2C,0x01。这使得我很难解析它们。

我可怕的(但工作)解决方案是将每个读取为字节,将每个转换为十六进制字符串,使用正则表达式替换将字符串操作为正确的顺序,然后将此十六进制字符串转换回十进制值。这太糟糕了我真的很尴尬;因此,为什么我想知道如何做得更好。

我的代码:

use Fcntl qw(:seek);

sub get_savegame_turn_number($);
sub read_file_hexdata_at_offset($$$);

sub get_savegame_turn_number($) {
    my ($filename) = @_;

    my $byteA = read_file_hexdata_at_offset($filename, 28, 1);
    my $byteB = read_file_hexdata_at_offset($filename, 29, 1);

    my $byteAhex = sprintf("%#02x", ord($byteA));
    my $byteBhex = sprintf("%#02x", ord($byteB));
    $byteAhex =~ s/^0x//;
    my $bytestring = $byteBhex . $byteAhex;

    return hex($bytestring);
}

sub read_file_hexdata_at_offset($$$) {
    my ($filename, $byte_position, $length) = @_;
    my($fh, $byte_value);

    open($fh, "<", $filename)
        || die "can't open $filename: $!";

    binmode($fh)
        || die "can't binmode $filename";

    sysseek($fh, $byte_position, SEEK_CUR)  # NB: 0-based
        || die "couldn't see to byte $byte_position in $filename: $!";

    sysread($fh, $byte_value, $length) == $length
        || die "couldn't read byte from $filename: $!";

    return $byte_value;
}

1 个答案:

答案 0 :(得分:2)

显示300的例子

$turn="\x2c\x01";
print unpack("S",$turn);