【问题标题】:getting decimal values from a binary file in perl从perl中的二进制文件中获取十进制值
【发布时间】:2021-01-03 02:34:16
【问题描述】:

我有一个包含我的数据的二进制文件。数据以 42 字节块为单位。我正在尝试逐块获取此数据并在 csv 文件中的行中打印等效的十进制值。目前我试图首先在屏幕上获取十进制数据。 使用 txt 编辑器打开文件时看起来像这样的东西:

 + Ö K¹Lÿ    ÿ    ÿ    ÿ    | D Ö ä
 + Ö K¹*ÿ    ÿ    ÿ    ÿ    | D Ö ä
 + Ö K¸4ÿ    ÿ    ÿ    ÿ    | D Ö ä
 + Ö Kµ*ÿ    ÿ    ÿ    ÿ    | D Ö ä
# 9 Ö K©[ÿ    ÿ    ÿ    ÿ    | D Ö ä
" 9 Ö K©‰ÿ    ÿ    ÿ    ÿ    | D Ö ä
+ 0 Ö K¯¿ÿ    ÿ    ÿ    ÿ    | D Ö ä
 9 Ö Kªµÿ    ÿ    ÿ    ÿ    | D Ö ä
 3 Ö K¨–ÿ    ÿ    ÿ    ÿ    | D Ö ä
 3 Ö Kªxÿ    ÿ    ÿ    ÿ    | D Ö ä
 Z Ö K¶:ÿ    ÿ    ÿ    ÿ    | D Ö ä
...

如果我用十六进制编辑器打开它,我会得到这个:

00 44 00 D6 00 E4 07 04 07 13 35 13 00 00 30 00 D6 00 4B C9 0D FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 7C 00 44 00 D6 00 E4 07 04 07 13 35 39 00 00 30 00 D6 00 4B C5 10 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 7C 00 44 00 D6 00 E4 07 04 07 13 36 16 00 00 33 00 D6 00 4B CE 44 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 7C 00 44 00 D6 00 E4 07 04 07 13 36 2F 00 00 30 00 D6 00 4B CE 12 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 7C 00 44 00 D6 00 E4 07 04 07 13 37 0C 00 00 33 00 D6 00 4B CE 21 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 7C 00 44 00 D6 00 E4 07 04 07 13 38 04 00 00 30 00 D6 00 4B D7 0A FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00 FF 00 00 00 00...

我的想法是一次读取一个字节的输入文件并将其存储在一个大小为 42 的数组中,然后转换 42 个字节并打印它们,然后继续下一个 42 个字节。 这就是我到目前为止所拥有的。我正在使用 perl 顺便说一句。 使用

use strict;
use warnings;
use diagnostics;
use feature 'say';
use feature "switch";
use v5.16;

my $input_file = 'pathtofile\ZONE0.txt'; 
open my $fh, '<', $input_file or die;
binmode $input_file;
my @decimal_values=[42];
my @buffer=[42];
while ( <$fh>) {
    my $i;
    for (my $i=0; $i<42; $i++) {
        read($fh, @buffer[$i], 1);
        my @decimal_values = map (eval("0b$_"), @buffer);
    }
    say @decimal_values;
}
    
    

当我执行代码时,我只收到这条消息:

Bareword found where operator expected at (eval 18248) line 1, near "0bb" (#3)

我不知道我做错了什么!

【问题讨论】:

  • 您的代码中有几个语法问题。您的while 循环正在检查包含文件路径的变量是否为真,因此它是无止境的。您应该看到一堆警告,因为您在较小的范围内重新声明了 $i。您的die 使用$_ 而不是$!,因此错误消息将不可见。用所有这些词法声明 @buffer 的那一行毫无意义。你到底想做什么?看起来您从网上收集了一堆不同的 Perl 示例并将它们组合在一起。
  • @simbabque 我的意思是在 while 循环中编写等效的 !eof 来解析整个文件。当我需要使用特定的字节进行以后的处理时需要缓冲线
  • map (eval("0b$_"), @buffer 这是要做什么?该文件是否包含二进制数据的 ascii 编码,例如0110010011...? (即:在文本格式中,因为您使用前缀 0b)另一方面,我猜该文件包含二进制数,因此数字 7 被编码为值为 7 的字节而不是 ascii 的 8 个字节值为“00000111”
  • @HåkonHægland 它是一个带有 0 和 1 的二进制文件,我正在尝试将该文件中的值转换为十进制并打印它们。我不确定 Methode 是否有效。我在问题中添加了更多信息。
  • use feature "switch",哇,好久没看到那个了。它是实验性的,当时不推荐,想知道它是否已经修复。我的猜测是否定的,你不应该尝试使用它。

标签: perl binary decimal


【解决方案1】:

这是一个如何在 Perl 中读取二进制文件的示例:

use feature qw(say);
use strict;
use warnings;
use constant BUFSIZE => 42;

my $input_file = 'ZONE0.dat';
open (my $BIN, "<:raw", $input_file) or die "can't open the file $input_file: $!";
my $buffer;
while (1) {
    my $bytes_read = sysread $BIN, $buffer, BUFSIZE;
    die "Could not read file $input_file: $!" if !defined $bytes_read;
    last if $bytes_read <= 0;
    my @decimal = map { unpack "C", $_ } split //, $buffer;
    say join ", ", @decimal;
}
close $BIN;

【讨论】:

  • 所以当文件的内容被读入$buffer时,$buffer会是一串42字节的对吧?
  • @waffles123 是的,这是正确的,对于while 循环的每次迭代,我们都会读取文件的 42 个字节
  • 这不是我所需要的。我想要一个 siye 42 的数组。因为我需要单数字节供以后使用。
  • @waffles123 字节被提取到数组@decimal
  • 好的,谢谢,最后一个问题。我拥有的文件是 .txt,但我看到您使用的是 .dat。这不会引起问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2013-08-23
  • 2022-06-22
  • 2012-08-20
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
相关资源
最近更新 更多