3 回答
TA贡献2011条经验 获得超2个赞
我只在一个小文件上尝试过这个,但原理与你读取文件、存储日期然后对其进行排序的想法非常相似。然后读取原始文件并写出排序后的数据。
在这个版本中,负载只是读取日期并创建一个数组,该数组保存日期和文件中行开头的位置(ftell()每次读取后使用以获取文件指针)。
然后对这个数组进行排序(因为日期首先只使用普通排序)。
然后它遍历已排序的数组,对于每个条目,它用于fseek()定位文件中的记录并读取该行(使用fgets())并将该行写入输出文件...
$file = "a.csv";
$out = "sorted.csv";
$handle = fopen($file, "r");
$tabligne = [];
$start = 0;
while ( $data = fgetcsv($handle) ) {
$tabligne[] = ['date' => DateTime::createFromFormat('d/m/Y', $data[2]),
'start' => $start ];
$start = ftell($handle);
}
sort($tabligne);
$outHandle = fopen( $out, "w" );
foreach ( $tabligne as $entry ) {
fseek($handle, $entry['start']);
$copy = fgets($handle);
fwrite($outHandle, $copy);
}
fclose($outHandle);
fclose($handle);
TA贡献1801条经验 获得超16个赞
假设您仅限于使用 PHP,并且不能按照评论中的建议使用数据库来实现它,那么下一个最佳选择是使用外部排序算法。
将文件拆分为小文件。这些文件应该足够小,以便在内存中对它们进行排序。
在内存中单独对所有这些文件进行排序。
通过比较每个文件的第一行,将排序后的文件合并为一个大文件。
排序文件的合并可以非常节省内存:在任何给定时间,您只需要在内存中保存每个文件的第一行。具有最小时间戳的第一行应转到结果文件。
对于非常大的文件,您可以级联合并,即:如果您有 10,000 个文件,您可以先合并 100 个文件的组,然后合并生成的 100 个文件。
例子
为了便于阅读,我使用逗号来分隔值而不是换行符。
未排序的文件(想象它太大而无法放入内存):
1, 6, 2, 4, 5, 3
将文件分成足够小以适合内存的部分:
1, 6, 2
4, 5, 3
分别对它们进行排序:
1, 2, 6
3, 4, 5
现在合并:
比较 1 & 3 → 取 1
比较 2 & 3 → 取 2
比较 6 & 3 → 取 3
比较 6 & 4 → 取 4
比较 6 & 5 → 取 5
取 6。
- 3 回答
- 0 关注
- 149 浏览
添加回答
举报