直接读取+重排+写入最稳妥:PHP无原生就地排序函数,file()+usort()适合中小文件,需用FILE_IGNORE_NEW_LINES等标志;大文件应流式处理或调用系统sort命令。

直接读取+重排+写入是最稳妥的做法
PHP 没有原生“就地修改文件行顺序”的函数,fgets() 或 file() 读出来的是数组,排序必须在内存中完成,再用 file_put_contents() 覆盖写回。试图用 fseek() + fwrite() 手动挪动行位置极易出错——换行符长度不一致(\n vs \r\n)、编码空格、BOM 头都会导致偏移错乱。
file() + usort() 是最常用组合
适用于中小文件(几百 MB 以内),代码简洁且可控。注意默认 file() 会保留换行符,排序后若需保持格式统一,建议先 rtrim() 再排序,最后手动补 \n:
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
usort($lines, function($a, $b) {
return strcmp($a, $b); // 字典序
// 或 intval($a) <=> intval($b); // 数值序(PHP 7+)
});
file_put_contents('data.txt', implode("\n", $lines) . "\n");
-
FILE_IGNORE_NEW_LINES避免每行末尾带\n干扰比较 -
FILE_SKIP_EMPTY_LINES过滤空行,防止strcmp('', 'xxx')返回意外结果 - 数值排序别直接用
sort($lines, SORT_NUMERIC)—— 它对字符串数字(如"10")排序不稳定,usort+ 强制转换更可靠
大文件慎用 file(),改用流式逐行读取+临时文件
超过 500MB 的文件,file() 可能触发内存耗尽(Allowed memory size exhausted)。此时应放弃一次性加载,改用 fopen() + fgets() 流式读取,把行内容和原始位置(或哈希)存到外部索引(如 SQLite 或临时 CSV),排序后再按序读取源文件写入新文件:
1.) 将所有文件解压到php环境中,本程序才用smarty+php+mysql设计。如果运行不了,请修改hhy文件夹下的smarty.php文件改法请看说明2.) 修改configs下的config.inc.php下的连接数据库的密码和用户名3.) 本程序没有做安全页面,人工导入sql.inc到mysql数据库。管理员初始化帐号为admin,密码为hhy。后台地址:http://你的网站地址/h
$fp = fopen('big.txt', 'r');
$tempLines = [];
while (($line = fgets($fp)) !== false) {
$tempLines[] = rtrim($line, "\r\n");
}
fclose($fp);
// 排序...
file_put_contents('big_sorted.txt', implode("\n", $tempLines) . "\n");
- 虽然仍全量载入内存,但至少避免了
file()自动加\n的副作用 - 真超大文件(GB 级)需配合外部排序工具(如系统
sort命令),PHP 只做调度:exec('sort -o sorted.txt big.txt'); - 注意
fgets()在 Windows 下对\r\n的处理比file()更干净,不易多出空行
按某列排序(如 CSV 第三列)要先解析再比
直接对 CSV 行字符串排序会出错(比如按字典序排数字列,“100” 会排在 “2” 前面)。必须用 str_getcsv() 拆解,提取目标字段再比较:
立即学习“PHP免费学习笔记(深入)”;
$lines = file('data.csv', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
usort($lines, function($a, $b) {
$aCols = str_getcsv($a);
$bCols = str_getcsv($b);
return $aCols[2] <=> $bCols[2]; // 按第3列(索引2)数值排序
});
file_put_contents('data.csv', implode("\n", $lines) . "\n");
-
str_getcsv()自动处理带引号、逗号转义的 CSV,比explode(',', $line)安全得多 - 若列含空值,
$aCols[2]可能未定义,建议加?? ''或array_key_exists(2, $aCols)判断 - UTF-8 编码下,
str_getcsv()默认按字节解析,遇到多字节字符(如中文)一般没问题;但若 CSV 用 BOM 开头,file()读出的首行可能含\xEF\xBB\xBF,需提前ltrim($line, "\xEF\xBB\xBF")










