【问题标题】:Read reversed bytes as decimal number from file从文件中读取反转字节作为十进制数
【发布时间】:2014-03-22 23:51:44
【问题描述】:

我正在尝试从 Perl 中的 Civilization 2 savegame 文件中读取轮数。我有一个很草率的解决方案,但一定有更优雅的解决方案。

它们以两个字节的形式存储在偏移量 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;
}

【问题讨论】:

  • 以小端序存储。查找pack 和(更具体地说)unpack
  • 关于工作的问题(但可能很混乱)通常属于 [代码审查](codereview.stackexchange.com/)。不过,这似乎是一个很好的问题。

标签: perl


【解决方案1】:

展示你的 300 示例

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

【讨论】:

  • 完美。非常感谢!
猜你喜欢
  • 2022-01-17
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多