
本文介绍如何正确读取目录中匹配特定命名规则(如 *-pairings.txt)的文件,构建成数组后序列化为 JSON 字符串,并安全写入磁盘文件(如 archives/contents.json),解决因未序列化或权限问题导致输出为空的常见错误。
本文介绍如何正确读取目录中匹配特定命名规则(如 `*-pairings.txt`)的文件,构建成数组后序列化为 json 字符串,并安全写入磁盘文件(如 `archives/contents.json`),解决因未序列化或权限问题导致输出为空的常见错误。
在 PHP 中,将目录文件列表导出为结构化 JSON 文件是一个高频需求,但初学者常因两个关键疏漏导致生成空文件:未对数组进行 JSON 编码(直接 fwrite($file, $array) 会写入 Array 字符串而非内容),以及未过滤隐藏文件或目标自身(如 .、.. 或刚生成的 contents.json)。以下提供健壮、可复用的解决方案。
✅ 推荐实现:支持通配符过滤的 JSON 导出函数
<?php /**
* 列出指定目录下匹配后缀的文件名,并写入 contents.json
* @param string $dir 目录路径(如 'archives')
* @param string|null $suffix 可选后缀过滤(如 '-pairings.txt'),留空则列出所有非系统文件
*/
function listContentsToJson(string $dir, ?string $suffix = null): bool
{
$dir = realpath($dir);
if (!$dir || !is_dir($dir)) {
error_log("目录不存在或不可访问: {$dir}");
return false;
}
$files = scandir($dir);
$contents = [];
foreach ($files as $file) {
// 跳过当前/上级目录、.DS_Store、contents.json 自身
if (in_array($file, ['.', '..', '.DS_Store', 'contents.json'], true)) {
continue;
}
// 若指定了后缀,仅保留匹配项(支持完整后缀匹配)
if ($suffix !== null && substr($file, -strlen($suffix)) !== $suffix) {
continue;
}
$contents[] = $file;
}
// 关键:必须 json_encode!否则 fwrite 写入的是 "Array" 字符串
$jsonContent = json_encode($contents, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if ($jsonContent === false) {
error_log('JSON 编码失败: ' . json_last_error_msg());
return false;
}
$targetPath = $dir . '/contents.json';
$result = file_put_contents($targetPath, $jsonContent);
if ($result === false) {
error_log("无法写入文件: {$targetPath}");
return false;
}
return true;
}
// ✅ 使用示例:仅列出 archives/ 下所有 *-pairings.txt 文件
listContentsToJson('archives', '-pairings.txt');
// ✅ 使用示例:列出所有非系统文件(无后缀限制)
// listContentsToJson('archives');
?>
⚠️ 原代码问题解析与修正要点
- 错误根源:原始代码中 fwrite($myfile, $arrFiles) 将数组直接传入,PHP 会将其强制转换为字符串 "Array",导致 contents.json 内容为纯文本 Array 而非 JSON 数组。
-
安全增强:
- 使用 realpath() 验证路径有效性;
- 显式排除 .、..、.DS_Store 和目标文件自身,避免循环写入;
- 添加 json_encode() 错误检查(json_last_error_msg());
- 使用 file_put_contents() 替代 fopen/fwrite/fclose,更简洁且原子性更强;
- 路径注意:确保 archives/ 目录存在且 Web 服务器用户(如 www-data)具有读取目录 + 写入文件权限(Linux/macOS 下常用 chmod 755 archives + chown www-data:www-data archives)。
? 进阶提示
- 如需按时间排序(如最新文件在前),可在构建 $contents 后添加:
usort($contents, function($a, $b) use ($dir) { return filemtime("{$dir}/{$b}") filemtime("{$dir}/{$a}"); }); - 若需递归遍历子目录,建议改用 RecursiveDirectoryIterator,但本场景中 scandir 更轻量高效。
执行该脚本后,archives/contents.json 将准确生成如下格式内容:
["2012-01-02-pairings.txt","2012-05-17-pairings.txt","2021-03-17-pairings.txt"]
结构清晰、可被前端 JavaScript 直接 fetch().then(r => r.json()) 解析,真正实现前后端数据契约。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











