代码之家  ›  专栏  ›  技术社区  ›  PeterK

如何用Perl将指定格式的数据写入二进制文件?

  •  2
  • PeterK  · 技术社区  · 14 年前

    2A02FC42 4

    您可以将其视为十六进制数(长度为 总是 8) 一个普通的数字。现在我需要以这种格式将所有行转储到一个二进制文件中(使用十六进制编辑器查看时应该是这样的):

    42FC022A00000004

    更多的例子说明:

    70726F67 36 676F727000000024
    6A656374 471 -&燃气轮机; 7463656A000001D7

    谢谢。

    编辑:更新了示例,忘记了在LE系统上的endiannes-im。

    3 回复  |  直到 14 年前
        1
  •  6
  •   Greg Bacon    14 年前

    使用 pack

    #! /usr/bin/perl
    
    use warnings;
    use strict;
    
    # demo only    
    *ARGV = *DATA;
    
    while (<>) {
      my($a,$b) = split;
      $a = join "", reverse $a =~ /(..)/g;
      $b = sprintf "%08x", $b;
    
      print pack "H*" => $a . $b;
    }
    
    __DATA__
    2A02FC42 4
    70726F67 36
    6A656374 471
    

    运行示例:

    $ ./prog.pl | od -t x1
    0000000 42 fc 02 2a 00 00 00 04 67 6f 72 70 00 00 00 24
    0000020 74 63 65 6a 00 00 01 d7
    0000030
        2
  •  1
  •   PP.    14 年前

    我的版本(已测试):

    my $fout;
    if ( ! open( $fout, ">/tmp/deleteme.bin" ) ) {
        die( "Failed to open /tmp/deleteme.bin: $!" );
    }
    binmode( $fout );
    
    while ( <DATA> ) {
        my ( $left, $right ) = split( /\s+/s, $_ );
    
        my $output = pack( "VN", hex($left), int($right) );
        printf(
            STDERR
            "  note, %8X %d -> " . ( "%02X" x 8 ) . "\n",
            hex($left), $right,
            map { $_ } unpack( "C8", $output )
        );
    
        print( $fout $output );
    }
    close( $fout );
    
    __DATA__
    70726F67 36 -> 676F727000000024
    6A656374 471 -> 7463656A000001D7
    

    输出:

    note, 70726F67 36 -> 676F727000000024
    note, 6A656374 471 -> 7463656A000001D7
    
        3
  •  0
  •   Grrrr    14 年前

    规范的方法是 pack . 假设您从文本文件中读取的数据已经转换为数字(包括十六进制数字),并存储在vars中 $x $y . 那你应该做些

     print OUTFILE pack("NN", $x, $y);
    

    如果需要不同的字节顺序,则必须使用 NN ,请参见 perldoc -f pack 详情。