Skip to content

Commit

Permalink
added FileSystem::readLines() [Closes #220]
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Feb 2, 2023
1 parent 78ac893 commit 53615ac
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/Utils/FileSystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,37 @@ public static function read(string $file): string
}


/**
* Reads the file content line by line. Because it reads continuously as we iterate over the lines,
* it is possible to read files larger than the available memory.
* @return \Generator<int, string>
* @throws Nette\IOException on error occurred
*/
public static function readLines(string $file, bool $stripNewLines = true): \Generator
{
return (function ($f) use ($file, $stripNewLines) {
$counter = 0;
do {
$line = Callback::invokeSafe('fgets', [$f], fn($error) => throw new Nette\IOException(sprintf(
"Unable to read file '%s'. %s",
self::normalizePath($file),
$error,
)));
if ($line === false) {
fclose($f);
break;
}
if ($stripNewLines) {
$line = rtrim($line, "\r\n");
}

yield $counter++ => $line;

} while (true);
})(static::open($file, 'r'));
}


/**
* Writes the string to a file.
* @throws Nette\IOException on error occurred
Expand Down
32 changes: 32 additions & 0 deletions tests/Utils/FileSystem.readLines.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/**
* Test: Nette\Utils\FileSystem readLines()
*/

declare(strict_types=1);

use Nette\Utils\FileSystem;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


test('readLines', function () {
FileSystem::write(getTempDir() . '/2/file', "\r\nHello\nWorld");

$lines = FileSystem::readLines(getTempDir() . '/2/file');
Assert::type(Generator::class, $lines);
Assert::same(['', 'Hello', 'World'], iterator_to_array($lines));

$lines = FileSystem::readLines(getTempDir() . '/2/file', stripNewLines: false);
Assert::type(Generator::class, $lines);
Assert::same(["\r\n", "Hello\n", 'World'], iterator_to_array($lines));
});


Assert::exception(
fn() => FileSystem::readLines('missing'),
Nette\IOException::class,
"Unable to open file 'missing'.%A%",
);

0 comments on commit 53615ac

Please sign in to comment.