jstewmc / chunker
使用PHP对非常大的文件或字符串进行分块(多字节安全)
Requires
- php: ^7.4 || ^8.0
- ext-mbstring: *
Requires (Dev)
- mikey179/vfsstream: ^1.6
- phpunit/phpunit: ^9
- roave/security-advisories: dev-latest
- slevomat/coding-standard: ^6
This package is auto-updated.
Last update: 2024-09-23 00:33:00 UTC
README
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许可证发布。