我正在尝试从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;
}
答案 0 :(得分:2)
显示300的例子
$turn="\x2c\x01";
print unpack("S",$turn);