wapmorgan/binary-stream

处理二进制数据的便捷工具

0.4.0 2017-06-18 01:02 UTC

This package is auto-updated.

Last update: 2024-08-27 06:16:59 UTC


README

BinaryStream - 处理二进制数据的便捷工具,是 pack()/unpack() 的最佳替代品,功能丰富。

Composer package Latest Stable Version Total Downloads License Latest Unstable Version Tests

如果您正在寻找一个方便的工具,可以读取和写入二进制数据(无论是现有的还是您创建的格式),您选择正确的库。

BinaryStream - 是读取和写入二进制文件的有效工具。它支持多种高级数据类型,有时甚至让您忘记您正在处理无结构的二进制数据。

使用 BinaryStream,您可以处理网络数据包、二进制文件、系统协议和其他底层数据。

  1. 特性
  2. 手册
  3. 参考
  4. 高级用法。写入

特性

  • 最低支持的 PHP 版本是 5.3.0 以使用所有功能。
  • 该库支持所有主要数据类型,并允许读取和写入数据。
  • 支持字节序的直接顺序(大端)和反向(小端)。您可以在读取文件时在这两者之间切换。
  • 支持多种尺寸的整数(8、16、32 和 64)以及罕见的(24、40、48 和 56)。
  • 支持多种尺寸的小数(32 和 64)。
  • 您可以读取单个字节和单个位。
  • 为了方便地在文件中导航,您可以命令 BinaryStream 记住文件中的某些位置,然后再次返回。
  • 支持数据组:保存配置一次,然后使用名称读取类似的数据组。
  • 支持配置文件来切换文件格式和版本。
  • 与标准 php 函数不同,它可以同时处理直接顺序的字节序(大端)和小端的小数

为什么它客观上优于 pack/unpack?

  • 64 位 int 的 float
  • float 的字节序选择
  • 罕见的,但可能 int 的大小(24、40、48、56)
  • 其他特性,如数据组和配置...

PHP 5.3 就有这些。

手册

简单用法

使用 BinaryStream 最简单的方法 - 这样

use wapmorgan\BinaryStream\BinaryStream;
$stream = new BinaryStream('filename.ext');
$text = $s->readString(20);

此示例读取文件开始的 20 个字节作为字符串。

一个更复杂的示例,其中数据按以下顺序排列

  • 整数(int,32 位)
  • 浮点数(float,32 位)
  • 标志字节(其中每个位都有自己的值,8 位):第一个位确定是否在此字节之后写入其他数据,5 位为空,数据的最后 2 位为数据类型
    • 0b00 - 在此数据之后记录 1 个字符(char,8 位)
    • 0b01 - 在此数据之后记录 10 个字符(字符串,10 字节)
    • 0b10 - 在此数据中包装在长整数(long,64 位)中的 unixtime 格式的日期时间
    • 0b11 - 目前未使用。

为了读取这些数据和依赖于标志的数据,此示例是合适的

use wapmorgan\BinaryStream\BinaryStream;
$stream = new BinaryStream('filename.ext');
$int = $stream->readInteger(32);
$float = $stream->readFloat(32);
$flags = $stream->readBits([
    'additional_data' => 1,
    '_' => 5, // pointless data
    'data_type' => 2,
]);
if ($flags['additional_data']) {
    if ($flags['data_type'] == 0b00)
        $char = $stream->readChar();
    else if ($flags['data_type'] == 0b01)
        $string = $stream->readString(10);
    else if ($flags['data_type'] == 0b10)
        $time = date('r', $stream->readInteger(64));
}

在此示例中,我们读取基本数据和基于标志值的基础数据。

但数据可能不会这么少。为了方便起见,您可以使用组读取函数。前面的示例可以重写如下

use wapmorgan\BinaryStream\BinaryStream;
$stream = new BinaryStream('filename.ext');
$data = $stream->readGroup([
    'i:int' => 32,
    'f:float' => 32,
    'additional_data' => 1,
    '_' => 5,
    'data_type' => 2,
]);
if ($data['additional_data']) {
    if ($data['data_type'] == 0b00)
        $data['char'] = $stream->readChar();
    else if ($data['data_type'] == 0b01)
        $data['string'] = $stream->readString(10);
    else if ($data['data_type'] == 0b10)
        $data['time'] = date('r', $stream->readInteger(64));
}

如果您正在读取一个包含重复数据组的文件,您可以保存一个带有名称的数据组,然后简单地引用它来读取下一个数据。让我们再介绍一个用于 data_type 的值:0b11 - 表示这是文件中的最后一个数据组。例如

use wapmorgan\BinaryStream\BinaryStream;
$stream = new BinaryStream('filename.ext');
$stream->saveGroup('Data', [
    'i:int' => 32,
    'f:float' => 32,
    'additional_data' => 1,
    '_' => 5,
    'data_type' => 2,
]);

do {
    $data = $stream->readGroup('Data');
    // Some operations with data
} while ($data['data_type'] != 0b11);

现在,假设我们已经切换到一个与之前不同的新文件格式,它在文件开头有一个特定的标记,这将帮助区分新旧格式。例如,一个新的标签是一个字符序列 'A', 'S', 'C'。我们需要检查标签,如果存在,则根据另一个方案解析文件,如果不存在,则使用旧版本的处理器。以下是一个示例

use wapmorgan\BinaryStream\BinaryStream;
$stream = new BinaryStream('filename.ext');

if ($stream->compare(3, 'ASC')) {
    // parse here new format
} else {
    $stream->saveGroup('DataOld', [
        'i:int' => 32,
        'f:float' => 32,
        'additional_data' => 1,
        '_' => 5,
        'data_type' => 2,
    ]);

    do {
        $data = $stream->readGroup('DataOld');
        // Some operations with data
    } while ($data['data_type'] != 0b11);
}

安装

通过 composer 安装

composer require wapmorgan/binary-stream

参考

数据类型

以下表格显示了所有使用的数据类型

API

  • 创建对象可以通过以下几种方式之一实现:new BinaryStream($filename | $socket | $stream)

  • 可以使用针对每种数据类型专门的方法读取数据

    • :
      • readBit(): 布尔值

        示例: $flag = $s->readBit();

      • readBits(array $listOfBits): 布尔值和整数的数组.

        示例: $flags = $s->readBits(['a' => 2, '_' => 5, 'b' => 3]); 如果字段的长度(数组元素的值是 1,则该字段将具有 true/false,如果大于 1,则 N 个连续位将组合成一个 integer。)

    • 字符:
      • readChar(): 字符串(1)

        示例: $char = $s->readChar();

      • readChars($count): 字符串(1)的数组

        示例: $chars = $s->readChars(4);

    • 整数
      • readInteger($sizeInBits = 32): 整数

        示例: $int = $s->readInteger(32); 它支持以下维度:8, 16, 32, 64 和 24, 40, 48, 56 位。

    • 浮点数:
      • readFloat($sizeInBits = 32): 浮点数

        示例: $float = $s->readFloat(32); 它支持以下维度:32, 64 位。

    • 字符串:
      • readString($length): 字符串($length)

        示例: $string = $s->readString(10);

字段组

您可以使用特定名称保存字段定义的列表,并在需要读取相同块多次时使用其名称。一个组由 组配置 定义 - 字段列表、字段类型和大小。要创建组配置,请创建一个数组: 定义字段类型和名称, - 它们的大小

  • 是字段的名称,可以包含字段类型。要指定类型,请在名称前加上类型字母和冒号。类型字母

    • b - 位
    • i - 整数
    • f - 浮点数
    • c - 字符
    • s - 字符串 如果未定义类型,则字段被视为 -字段。示例: flag - -字段,s:name - 字符串-字段
  • 是字段的大小或维度

    • 如果字段具有 integerfloatbit 类型,则它定义了字段以位为单位的大小。
    • 如果字段具有 charstring 类型,则它定义了以字节为单位的大小。示例
    'flags' => 16, // bits-field (16 bits = 2 bytes)
    's:name' => 10, // string-field (80 bits = 10 bytes)

所以完整的组配置示例

$group = [
    'flags' => 16,
    'i:date' => 32,
    'f:summ' => 32,
    's:name' => 10,
];

导航

  • 光标移动:要更改文件中的光标位置,请使用以下方法。
  • 当前位置测试

    isEnd(): boolean

    如果光标在文件末尾,则返回 true

  • 记住文件中的位置

辅助

  • 字节比较

    compare($length, $bytes)

    比较当前位置 $length 个字节与 $bytes。当前位置不会改变。返回 truefalse

  • 字节序:默认情况下,BinaryStream 以小端格式处理 intlong。要更改字节读取顺序,请使用 setEndian($endian) 方法并使用 BinaryStream 常量之一

配置

高级用法。写入

如果您需要向二进制文件写入数据,则可以使用额外的方法来完成此操作。

首先,您需要以允许写入文件的模式之一打开一个文件(默认情况下,文件以只读模式打开)。为此,当您创建一个BinaryStream对象时,在第二个参数中指定以下模式之一:

正确打开文件后,您可以使用以下方法,这些方法的名字与为读取设计的方法类似。