jstewmc/chunker

使用PHP对非常大的文件或字符串进行分块(多字节安全)

v0.2.1 2021-10-22 18:22 UTC

This package is auto-updated.

Last update: 2024-09-23 00:33:00 UTC


README

CircleCI codecov

Chunker

这是一个多字节安全的流,用于使用PHP将非常大的文件(或字符串)作为顺序块读取。

将非常大的文件或字符串分割成块并逐个读取(即“分块”)可以减少内存消耗。

遗憾的是,分块多字节编码的文件,如使用UTF-8的文件,可能会导致多字节字符损坏。PHP的文件函数,如file_get_contents(),使用字节限制。当限制落在多字节字符的中间时,将出现不规则的字节序列,这由"?"字符表示

// Create an example file with multi-byte characters (characters in the string
// "from $ to " are one-byte in UTF-8, while the euro symbol, "€", is a three-
// byte character in UTF-8)
file_put_contents('example.txt', 'from $ to €');

// Read 12 bytes of the file.
$length = 12;

echo file_get_contents('example.txt', false, null, 0, $length);

上面的示例将产生以下输出

from $ to ?

"?"出现,因为示例文件内容的12个字节位于三个字节的欧元符号中间。这导致不规则的字节序列,PHP用"?"字符表示。

此库以多字节安全的方式对非常大的文件(和字符串)进行分块。它略微调整块大小以确保每次都形成良好的字节序列

use Jstewmc\Chunker\Text;

// Instantiate a new text chunker with UTF-8 encoding and a chunk size of four
// bytes (these constructor arguments are covered in more detail below).
$chunker = new Text('from $ to €', 'UTF-8', 4);

// Loop through the file's chunks, echo the chunk, and advance to the next one.
while (false !== ($chunk = $chunker->current())) {
	echo "'$chunk'";
	$chunker->next();
}

上面的示例将产生以下输出

'from'
' $ t'
'o '
'€'

请注意,第三个块只有两个单字节字符,最后一个块是单个三字节字符。

安装

此库需要PHP 7.4+

它是多平台的,我们努力使其在Windows、Linux和OSX上运行得同样好。

应通过Composer进行安装。为此,请将以下行添加到您的composer.json文件的require部分,并运行composer update

{
   "require": {
       "jstewmc/chunker": "^0.2"
   }
}

实例化分块器

有两种类型的分块器:文件文本

实例化文件分块器

您可以使用文件路径名实例化一个File分块器

use Jstewmc\Chunker\File;

$chunker = new File('path/to/file.ext');

实例化文本分块器

您可以使用字符串实例化一个Text分块器

use Jstewmc\Chunker\Text;

$chunker = new Chunker\Text('foo bar baz');

设置字符编码

文件或字符串的字符编码让PHP知道如何理解其内容。

您可以明确设置文件(或字符串的)字符编码 - 使用分块器的构造函数参数 - 或者您可以允许此库隐式设置它 - 使用您应用程序的内部字符编码。

明确设置字符编码

要明确设置文件或字符串的字符编码,请使用构造函数的第二个参数$encoding。如果您知道文件或字符串与您的应用程序的编码不同,这很有用。编码必须是一个有效的字符编码,来自PHP的多字节字符串库

use Jstewmc\Chunker\Text;

$chunker = new Text('foo', 'UTF-8');

隐式设置字符编码

要允许此库隐式设置文件或字符串的字符编码,请勿向构造函数传递字符编码。假设块的编码是您应用程序的内部字符编码,PHP的mb_internal_encoding()返回的值

use Jstewmc\Chunker\Text;

$chunker = new Text('foo');

设置块大小

分块器的“块大小”设置决定了每个块所占用的内存。该库尝试提供合理的默认值:文件为8,192个字节,字符串为2,000个字符(大约8,000个字节)。

要更改块大小,请使用构造函数的第三个参数$size(记住,对于文件是字节,对于文本是字符)

use Jstewmc\Chunker\{File, Text};

// Use chunks of 8,192 bytes.
$chunker1 = new File('/path/to/file.ext', null, 8192);

// Use chunks of 2,000 characters.
$chunker2 = new Text('foo bar baz', null, 2000);

消费块

分块器旨在模拟流或块的数组。

您可以使用getCurrentChunk()(别名,current()),getNextChunk()(别名,next()),和getPreviousChunk()(别名,previous())在块之间导航(如果不存在块,则方法将返回false)

use Jstewmc\Chunker\Text;

$chunker = new Text('foo');

$chunker->getCurrentChunk();   
// returns "foo" (the first chunk is immediately available upon instantiation)

$chunker->getNextChunk();      
// returns false (advances the internal pointer and returns next chunk)

$chunker->getPreviousChunk();  
// returns "foo" (rewinds the internal pointer and returns previous chunk)

$chunker->getCurrentChunk();   
// returns "foo"

$chunker->getCurrentChunk();   
// returns "foo" (because the internal pointer hasn't moved)

这些方法通常在while循环中结合使用(请注意,严格比较块值与false非常重要;它可能返回布尔false,也可能返回非布尔值,该值评估为false

while (false !== ($chunk = $chunker->current())) {
	//
	// do something with the $chunk...
	//
	// advance the pointer for the next iteration
	$chunker->next();
}

导航方法是幂等的(即,在输入末尾调用next()不会更新内部块索引),但块只在单向保证确定性(即,向前的最后一个块可能不等于向后的第一个块)。

您可以使用countChunks()方法计算文件或字符串中的块数

use Jstewmc\Chunker\Text;

$chunker = new Text('foo bar baz', null, 3);

$chunker->countChunks();  // returns 4 (the count is always rounded up)

您可以使用hasChunk()hasChunks()来查看文件或字符串是否恰好有一个块或有一个或多个块,分别

use Jstewmc\Chunker\Text;

$chunker1 = new Text('foo', null, 3);

$chunker1->hasChunk();   // returns true
$chunker1->hasChunks();  // returns true

$chunker2 = new Text('foo bar', null, 3);

$chunker->hasChunk();   // returns false (there are three, three-char chunks)
$chunker->hasChunks();  // returns true

您可以使用hasPreviousChunk()hasNextChunk()来查看文件或字符串是否有一个前一个块或一个后一个块,分别

use Jstewmc\Chunker\Text;

$chunker = new Text('foo bar', null, 3);

$chunker->countChunks();  // returns 3 (there are three, three-character chunks)

$chunker->hasPreviousChunk();  // returns false (the pointer is at zero)
$chunker->hasNextChunk();      // returns true

$chunker->next(); // advance to the next chunk

$chunker->hasPreviousChunk();  // returns true
$chunker->hasNextChunk();      // returns true

$chunker->next();

$chunker->hasPreviousChunk();  // returns true
$chunker->hasNextChunk();      // returns false (the pointer it at the end)

最后,您可以使用reset()将分块器的内部指针重置为零

use Jstewmc\Chunker\Text;

$chunker = new Text('foo bar', null, 3);

$chunker->current();  // returns "foo"

$chunker->next();     // returns " ba"
$chunker->current();  // returns " ba"

$chunker->reset();    

$chunker->current();  // returns "foo"

贡献

欢迎贡献!以下是开始步骤

# Clone the repository (assuming you have Git installed).
~/path/to $ git clone git@github.com:jstewmc/chunker.git

# Install dependencies (assuming you are using Composer locally).
~/path/to/chunker $ php composer.phar install

# Run the tests.
~/path/to/chunker $ ./vendor/bin/phpunit

# Create and checkout a new branch.
~/path/to/chunker $ git branch -c YOUR_BRANCH_NAME

# Make your changes...

# Run the tests again.
~/path/to/chunker $ ./vendor/bin/phpunit

# Lint your changes.
~/path/to/chunker $ ./vendor/bin/phpcs .

# Fix the issues you can automatically.
~/path/to/usps-address $ ./vendor/bin/phpcbf .

# Push your changes to Github and create a pull request.
~/path/to/chunker $ git push origin YOUR_BRANCH_NAME

许可证

此库根据MIT许可证发布。