gugglegum/memory-size

基于标准的内存或文件大小解析器和格式化工具

1.0.3 2021-05-01 17:25 UTC

This package is auto-updated.

Last update: 2024-08-29 03:52:53 UTC


README

这是一个简单的Composer包,用于处理内存块或文件的人性化格式大小(如“32 KB”,“4.87 MiB”等)。它由两部分组成:解析器和格式化器。解析器允许解析人性化的格式大小。而格式化器允许将大小格式化为人性化视图。它们相互兼容,因此解析器可以解析由格式化器生成的字符串,反之亦然。此包侧重于国际标准,您可以添加自己的标准实现。通常这里有两个主要的标准可用:

  1. JEDEC标准100B.01 (JESD100B.01) (https://en.wikipedia.org/wiki/JEDEC_memory_standards)
  2. ISO/IEC 80000 (https://en.wikipedia.org/wiki/ISO/IEC_80000)

JESD100B.01描述了旧式的度量单位,如“KB”,“MB”和“GB”,分别表示1024字节,1024^2字节和1024^3字节。虽然这些度量单位广为人知且流行,但由于它们与SI(公制)前缀冲突(其中“M”表示1000^2(百万),“G”表示1000^3(十亿)),因此已被弃用。顺便说一下,使用“Kilo”前缀没有冲突,因为SI前缀的“Kilo”定义为“k”(小写)。此外,JESD100B.01允许使用仅包含前缀的缩写记录,例如“K”,“M”和“G”。这些记录有些令人困惑,但不如“KB”,“MB”和“GB”那样不一致。请注意,JESD100B.01仅定义了千字节、兆字节和吉字节。它没有定义太字节、拍字节等。因此,“TB”单位不应被视为1024^4。如果您需要一个定义了“TB”、“PB”等的标准,您可以编写自己的标准实现并将其设置为解析器或格式化器。或者您可以直接联系我,提出您自己的优雅解决方案。

ISO/IEC 80000是一个更现代的标准。它通过引入新的二进制前缀来解决内存前缀和SI前缀不一致的问题,特别是对于2的幂次方:例如,“KiB”,“MiB”,“GiB”,“TiB”,“PiB”等,分别表示1024,1024^2,1024^3,1024^4,1024^5等。但此标准也引用了SI前缀。因此,“1 MB”表示1000000(1000^2)字节,“1 GB”表示1000000000(1000^3)字节,依此类推。

这两个标准(JESD100B.01和ISO/IEC 80000)作为具有标准接口的独立类实现。您可以定义要使用哪个标准和顺序,或者您可以创建自己的标准实现并将标准实例传递给解析器或格式化器。

解析器

例如,您希望从用户那里接受任何大小的字节数(例如,通过配置文件或命令行参数)。当然,您可以强制用户指定确切的字节数。但是,当涉及到千兆字节和太字节时,这并不太方便。或者,也许您需要解析已经包含格式化文件大小的数据,例如“700M”或“4.38GB”。您可以使用此解析器进行此操作。以下是一个示例

<?php

require_once __DIR__ . '/vendor/autoload.php';

$parser = new \gugglegum\MemorySize\Parser();
var_dump($parser->parse('700M'));

将生成以下输出

int(734003200)

解析器使用标准的实现来解析格式化的大小。它可以使用几个标准。首先它尝试使用第一个标准解析单位。如果它不知道这个单位,它将尝试第二个,以此类推。默认情况下,解析器使用ISO/IEC 80000作为第一个(主要)和JESD100B.01作为第二个(次要)。因此,它将正确解析“32K”形式和“32 KiB”。但是,如果您需要将“8 MB”或“2 GB”作为二进制前缀处理,您需要删除ISO/IEC 80000标准或将JESD100B.01设置为第一个(主要)。

这是一个如何将JESD100B.01标准设为主要,ISO/IEC 80000标准设为次要的示例

<?php

require_once __DIR__ . '/vendor/autoload.php';

$parser = new \gugglegum\MemorySize\Parser([
    'standards' => [
        new \gugglegum\MemorySize\Standards\JEDEC(),
        new \gugglegum\MemorySize\Standards\IEC(),
    ],
]);

var_dump($parser->parse('32 kB'));
var_dump($parser->parse('32 KB'));
var_dump($parser->parse('32 KiB'));

var_dump($parser->parse('8 MB'));
var_dump($parser->parse('8 MiB'));

将生成以下输出

int(32000)
int(32768)
int(32768)
int(8388608)
int(8388608)

您可能在这里看到,“32 kB”解析为32000,因为小写“k”前缀是SI前缀。二进制千字节前缀是大写“K”。这就是为什么“32 KB”解析为32768而“32 kB”解析为32000的原因。“32 KiB”始终由ISO/IEC 80000解析为32768,因为“Ki”是一个特殊的二进制前缀,称为“kibi”。“8 MB”解析为8388608,因为JEDEC是主要的,它将此前缀视为二进制。“8 MiB”始终由ISO/IEC 80000解析为8388608,因为“Mi”是一个特殊的二进制前缀,称为“mebi”。

解析器选项

默认解析器选项适用于95%的情况,因此您可能不需要任何选项就实例化解析器,就像第一个示例中那样。在剩下的5%的情况下,您可以在解析器构造函数中作为关联数组传递以下选项,或使用设置方法。您可能只需传递要更改的默认选项。

  • standards — 实现\gugglegum\MemorySize\Standards\StandardInterface的1个或多个对象的数组。
  • numberFormats — 1个或多个\gugglegum\MemorySize\NumberFormat类的对象或具有“decimalPoint”和“thousandsSeparator”键的关联数组。
  • allowNegative — 表示是否允许负值的布尔值。如果不允许,包含负内存大小值的字符串将无法解析。

初始化示例

使用传递给构造函数的关联数组

$parser = new \gugglegum\MemorySize\Parser([
    'standards' => [
        new \gugglegum\MemorySize\Standards\JEDEC(),
        new \gugglegum\MemorySize\Standards\IEC(),
    ],
    'numberFormats' => [
        \gugglegum\MemorySize\NumberFormat::create(',', ' '),
        \gugglegum\MemorySize\NumberFormat::create('.', ','),
    ],
    'allowNegative' => false,
]);

相同的,但略有不同

$parser = new \gugglegum\MemorySize\Parser([
    'standards' => [
        new \gugglegum\MemorySize\Standards\JEDEC(),
        new \gugglegum\MemorySize\Standards\IEC(),
    ],
    'numberFormats' => [
        [
            'decimalPoint' => ',',
            'thousandsSeparator' =>  ' ',
        ],
        new \gugglegum\MemorySize\NumberFormat([
            'decimalPoint' => ',',
            'thousandsSeparator' =>  ' ',
        ])
    ],
    'allowNegative' => false,
]);

使用设置器的相同示例的另一个变体

$parser = new \gugglegum\MemorySize\Parser();
$parser->getOptions()->setStandards([
        new \gugglegum\MemorySize\Standards\JEDEC(),
        new \gugglegum\MemorySize\Standards\IEC(),
    ])->setNumberFormats([
        \gugglegum\MemorySize\NumberFormat::create(',', ' '),
        \gugglegum\MemorySize\NumberFormat::create('.', ','),
    ])->setAllowNegative(false);

格式化器

与解析器相反,您可能需要一个格式化器来以人类友好的视图格式化内存大小或文件大小。格式化器也使用标准对象。但是,与解析器不同,格式化器一次只能使用一个标准。默认情况下,格式化器使用ISO/IEC 80000标准,并使用二进制前缀(“KiB”、“MiB”、“GiB”等)。以下是使用格式化器的示例

<?php

require_once __DIR__ . '/vendor/autoload.php';

$formatter = new \gugglegum\MemorySize\Formatter();
var_dump($formatter->format(32768));
var_dump($formatter->format(1536));
var_dump($formatter->format(1000000));
var_dump($formatter->format(1048576));

将生成以下输出

string(6) "32 KiB"
string(7) "1.5 KiB"
string(10) "976.56 KiB"
string(5) "1 MiB"

如果您需要JESD100B.01的旧式格式,您可以将它设置为使用它而不是ISO/IEC 80000。以下是这样做的方法

<?php

require_once __DIR__ . '/vendor/autoload.php';

$formatter = new \gugglegum\MemorySize\Formatter([
    'standard' => new \gugglegum\MemorySize\Standards\JEDEC(),
]);
var_dump($formatter->format(32768));
var_dump($formatter->format(1536));
var_dump($formatter->format(1000000));
var_dump($formatter->format(1048576));

将生成以下输出

string(5) "32 KB"
string(6) "1.5 KB"
string(9) "976.56 KB"
string(4) "1 MB"

格式化器选项

默认格式化器选项对于大多数情况已经足够好,但如果需要,您可以自定义它们。您可以将以下选项作为关联数组传递给格式化器构造函数或使用设置方法。您可能只需传递要更改的默认选项。

  • standard — 实现\gugglegum\MemorySize\Standards\StandardInterface的对象。与解析器不同,格式化器在格式化值时只使用一个标准。
  • minDecimals — 最小小数位数(整数)。
  • maxDecimals — 最大小数位数(整数)。
  • fixedDecimals — 最小和最大小数位数之和(整数)。
  • numberFormat\gugglegum\MemorySize\NumberFormat类的对象或具有“decimalPoint”和“thousandsSeparator”键的关联数组。
  • unitSeparator — 数字和测量单位之间的分隔符,通常是空格字符或空字符串。

初始化示例

使用传递给构造函数的关联数组

$formatter = new \gugglegum\MemorySize\Formatter([
    'standard' => new \gugglegum\MemorySize\Standards\IEC(),
    'minDecimals' => 1,
    'maxDecimals' => 3,
    'numberFormat' => \gugglegum\MemorySize\NumberFormat::create(',', ' '),
    'unitSeparator' => ' ',
]);

略有不同的相同变体

$formatter = new \gugglegum\MemorySize\Formatter([
    'standard' => new \gugglegum\MemorySize\Standards\IEC(),
    'minDecimals' => 1,
    'maxDecimals' => 3,
    'numberFormat' => [
        'decimalPoint' => ',',
        'thousandsSeparator' =>  ' ',
    ],
    'unitSeparator' => ' ',
]);

创建您自己的标准实现

如上所述,您能够创建自己的标准实现来按您想要的任何方式解析和格式化内存大小。您需要创建一个类,该类实现\gugglegum\MemorySize\Standards\StandardInterface,该接口定义以下方法

    /**
     * Resolves unit of measure into multiplier. Return FALSE if unable to resolve. This method is used only in the Parser.
     *
     * @param string        $unit
     * @return float|int|false
     */
    public function unitToMultiplier(string $unit);

    /**
     * Returns associative array of measurement units where keys are units and values are multipliers corresponding to
     * the units. For example: [ 'B' => 1, 'KiB' => 1024, 'MiB' => 1048576, ... ] This method is used only in the Formatter,
     * only these measurement units will be used in formatted memory size.
     *
     * @return array
     */
    public function getByteUnitMultipliers(): array;

假设您需要一个定义内存大小记录为比特、K比特和M比特的标准。它可能看起来像这样

<?php

require_once __DIR__ . '/vendor/autoload.php';

class BitSizeStandard implements \gugglegum\MemorySize\Standards\StandardInterface
{
    /**
     * Resolves unit of measure into multiplier (this method is used only in Parser)
     *
     * @param string        $unit
     * @return float|int|false
     */
    public function unitToMultiplier(string $unit)
    {
        switch ($unit) {
            case 'bit' :
                return 1/8;
            case 'Kbit' :
            case 'kbit' :
                return 1/8 * 1024;
            case 'Mbit' :
            case 'mbit' :
                return 1/8 * 1024 * 1024;
            default :
                return false;
        }
    }

    /**
     * Returns associative array of measurement units where keys are units and values are multipliers corresponding to
     * the units. For example: [ 'B' => 1, 'KiB' => 1024, 'MiB' => 1048576, ... ] (this method is used only in Formatter)
     *
     * @return array
     */
    public function getByteUnitMultipliers(): array
    {
        return [
            'bit' => 1/8,
            'Kbit' => 1/8 * 1024,
            'Mbit' => 1/8 * 1024 * 1024,
        ];
    }
}

$formatter = new \gugglegum\MemorySize\Formatter([
    'standard' => new BitSizeStandard(),
]);

$formattedSize = $formatter->format(1024);
echo $formattedSize, "\n";

$parser = new \gugglegum\MemorySize\Parser([
    'standards' => [
        new BitSizeStandard(),
    ],
]);

echo $parser->parse($formattedSize), "\n";

您可能会注意到,第一种方法解析的测量单位比第二种方法多。它允许解析器解析同一测量单位的多种形式。

要求

此包需要PHP版本7.1及以上。