PHP如何将从二进制文件中读取的字节转换为数字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP如何将从二进制文件中读取的字节转换为数字相关的知识,希望对你有一定的参考价值。

$a=fread($file,4);
变量$a 从二进制文件$file中读取了4个字节的数据,已经知道这四个字节代表一个整数
请问这样才能将$a 转换为整数,能正确输出和能进行如if($a>20)这样数值比较,

参考技术A bindec函数可转换二进制数为十进制数追问

bindec函数不行,bindec函数只是能将 $a="10010101";这样像二进制数 的字符串或者数字转换为10进制,我的那个是可是从文件中读取出来的4个字节哦~

追答

怎么就不可以了?fread函数的返回值难道还不是字符串么?

追问

我试过了,不行的,得进行高低位转换才可以

参考技术B bindec 这个函数可以 参考技术C $a=fread(....);//读4个字节
$d=unpack(‘V’,$a); //按32bit无符号小端解码。大端用字母N

echo $d[0];

另,手工计算也可以
$a=fread(....);//读4个字节

$d=ord($a[0]);
$d|=ord($a[1])<<8;

$d|=ord($a[2])<<16;

$d|=ord($a[3])<<24;

按小端计算本回答被提问者采纳

如何从二进制文件中读取块并使用 Python 或 Perl 解包提取结构?

【中文标题】如何从二进制文件中读取块并使用 Python 或 Perl 解包提取结构?【英文标题】:How can I read a block from a binary file and extract structs using unpack using Python or Perl? 【发布时间】:2012-06-28 22:26:36 【问题描述】:

我有一个二进制文件,它有 4 KB 的标头信息,然后是 28 字节的数据,然后是我想要读取的 24 字节。我如何每 24 和 28 字节循环并读取(或提取)这 28 和 24 字节的前 8 字节数据。在 python 中我做了这样的事情。不知道如何处理可变长度

import sys
import struct
f = open(sys.argv[1],"rb")
f.seek(4096)
byte = f.read(28)
while byte != "":   
    ticks = struct.unpack("<ll",byte[:8]) #not sure how to read 8 bytes 
    byte = f.read(28)
f.close()

这是标题之后的样子。

Length
(bytes) Field Name
8   TS_INCR
4   SEQID
2   OP
2   LUN
4   NBLKS
8   LBA


Length
(bytes) Field Name
8   TS_INCR
4   SEQID
2   OP
2   LUN
4   LATENCY_TICKS
2   HOST_ID
2   HOST_LUN

如果你们能帮忙解决这个问题,请。 Python 或 PERL 无关紧要。谢谢!!!!

【问题讨论】:

【参考方案1】:

您正在阅读的数据的Endianness 很重要。您似乎将 8 个八位字节解包为以小端顺序存储的两个长字节。您确定它不是单个 64 位数量(这会使 qQ 格式更合适)?不幸的是,我在 32 位机器上,所以我的 perl 不支持 Q

但是,以下内容应为您指明正确的方向:

#!/usr/bin/env perl

use strict; use warnings;
use autodie;

use Fcntl qw(:seek);
use List::Util qw( sum );

my ($input_file) = @ARGV;
die "Need input file\n" unless defined $input_file;

my $HEADER_SIZE = 4_096;

my @typedef = (
    
        fields => [
            qw(
                TS_INCR_LO
                TS_INCR_HI
                SEQID
                OP
                LUN
                NBLKS
                LBA_LO
                LBA_HI
            )
        ],
        tmpl => 'LLLSSLLL',
        start => 0,
        size => 28,
    ,
    
        fields => [
            qw(
                TS_INCR_LO
                TS_INCR_HI
                SEQID
                OP
                LUN
                LATENCY_TICKS
                HOST_ID
                HOST_LUN
            )
        ],
        tmpl => 'LLLSSLSS',
        start => 28,
        size => 24,
    ,
);

open my $input, '<:raw', $input_file;

seek $input, $HEADER_SIZE, SEEK_SET;

my $BLOCK_SIZE = sum map $_->size, @typedef;
read $input, my($buffer), $BLOCK_SIZE;

my @structs;

for my $t ( @typedef ) 
    my %struct;
    @struct @ $t->fields  = unpack(
        $t->tmpl,
        substr($buffer, $t->start, $t->size)
    );
    push @structs, \%struct;


use Data::Dumper;
print Dumper \@structs;

【讨论】:

谢谢。对不起,我不擅长 perl。这个程序是在读取这 28 个字节和 24 个字节中的前 8 个字节吗? 它将整个结构解压缩到 Perl 哈希中。 TS_INCR_LO 是每个块中的前四个八位位组,TS_INCR_HI 是组成TS_INCR 的第二组四个八位位组。您需要将两者结合起来。 我使用的是 64 位机器。所以如果我使用'Q'。我不必那样做,对吧?像 tmpl=> 'QLSSLQ'? 是的。而不是*_LO*_HI,您使用单个字段。 HTH。【参考方案2】:

我想我会阅读 52 每个循环的字节数 (24+28==52) 并简单地索引到您关心的字节数。它看起来像这样:

byte = f.read(52)
while byte != "":   
    ticks = struct.unpack("<ll",byte[0:8])
    tocks = struct.unpack("<ll",byte[28:36])
    byte = f.read(52)

请注意,我不知道 while byte != "" 是否是这种情况下的惯用循环。我只是建议读取更大的块并仅解析您感兴趣的字节。操作系统级别的read() 操作非常慢,将它们减半将使您的应用程序的速度大约翻倍。如果您改为读取更大的数据块,您肯定会获得更大的加速——但这可能需要比这个微小的改变更多的重写。

【讨论】:

感谢您的快速回复。我做了'Q'而不是'll'。这是第一个输出,但最后的'L'是什么意思==>(7205759403792853089L,) L 表示它的类型为long

以上是关于PHP如何将从二进制文件中读取的字节转换为数字的主要内容,如果未能解决你的问题,请参考以下文章

Pentaho Kettle - 从二进制类型的字段将十六进制转换为数字

读取二进制文件碎片并转换为具有内存效率的整数

使用 ifstream 从二进制文件中读取 4 个字节

将任何文件转换为二进制字符串并从二进制转换为文件[关闭]

从二进制文件中读取并转换为双精度?

在 C++ 中写入整数并从二进制文件中读取它们:字节数 mismaych