我有一个很大的CSV文件。由于内存问题(MySQL),如果可能的话,我希望一次只读取其中的一部分。
它是CSV可能并不重要。重要的是,它需要用一个新的行来截断。
示例内容:
Some CSV content
that will break
on a line break
这可能是我的路径:
$path = 'path/to/my.csv';
在我看来,它的解决方案可能是这样的:
$csv_content1 = read_csv_file($path, 0, 100);
$csv_content2 = read_csv_file($path, 101, 200);
- 读取第0-100行原始内容。
- 读取101-200行的原始内容。
- 不需要解析(只拆分为内容)。 文件存在于我自己的服务器上。不要把整个文件读到内存中。
- 我希望能够在另一个时间做第二次读取,而不是在同一运行。如果需要,我接受像指针一样保存临时值。
我一直在尝试阅读其他主题,但没有找到与此问题完全匹配的主题。
也许其中一些可以以某种方式工作?
- SplFileObject
- :
也许我不能在使用$csv_content1
之前使用$csv_content2
,因为我需要保存某种指针?那样的话就好了。我还是按顺序读吧
经过深思熟虑和阅读,我终于认为我找到了解决问题的方法。如果这是一个糟糕的解决方案,因为内存使用或从其他角度,请纠正我。
首次运行
$buffer = part($path_to_file, 0, 100);
下运行$buffer = part($path_to_file, $buffer['pointer'], 100);
function part($path, $offset, $rows) {
$buffer = array();
$buffer['content'] = '';
$buffer['pointer'] = array();
$handle = fopen($path, "r");
fseek($handle, $offset);
if( $handle ) {
for( $i = 0; $i < $rows; $i++ ) {
$buffer['content'] .= fgets($handle);
$buffer['pointer'] = mb_strlen($buffer['content']);
}
}
fclose($handle);
return($buffer);
}
在我更面向对象的环境中,它看起来更像这样:
function part() {
$handle = fopen($this->path, "r");
fseek($handle, $this->pointer);
if( $handle ) {
for( $i = 0; $i < 2; $i++ ) {
if( $this->pointer != $this->filesize ) {
$this->content .= fgets($handle);
}
}
$this->pointer += mb_strlen($this->content);
}
fclose($handle);
}