从零开始:PHP 文件读写全攻略
在PHP开发中,文件读写是处理数据持久化、配置管理和日志记录的核心技能。无论是读取用户上传的CSV文件,还是生成动态配置,掌握文件操作都能帮助开发者构建更健壮的应用。本文将从基础语法到实战场景,系统讲解PHP文件读写的关键知识点与最佳实践。
一、文件读取基础:从打开到关闭
PHP通过fopen()函数打开文件,返回文件资源句柄,后续操作基于此句柄。常见的文件打开模式及适用场景如下:
| 模式 | 含义 | 适用场景 |
|---|---|---|
r |
只读,文件必须存在 | 读取已存在的文本文件 |
r+ |
读写,文件必须存在 | 需同时读写的场景 |
w |
只写,覆盖原内容,文件不存在则创建 | 新建或覆盖写入文件 |
a |
只写,追加内容,文件不存在则创建 | 日志记录、数据追加 |
1. 逐行读取文本文件
对于大文件,逐行读取可避免一次性加载全部内容到内存。使用fgets()配合循环实现:
// 打开文件
$handle = fopen('data.txt', 'r');
if ($handle) {
// 循环读取每一行
while (($line = fgets($handle)) !== false) {
echo trim($line) . '<br>'; // 输出每行内容
}
fclose($handle); // 必须关闭文件句柄
} else {
echo "文件打开失败";
}
2. 一次性读取文件内容
小文件可直接用file_get_contents()简化操作:
$content = file_get_contents('small.txt');
if ($content === false) {
die("文件读取失败:可能不存在或权限不足");
}
echo "文件内容:" . $content;
二、文件写入基础:覆盖与追加
文件写入需明确“覆盖”或“追加”模式,核心函数为fwrite()和file_put_contents()。
1. 覆盖写入文件
使用w模式打开文件,原有内容会被清空:
$content = "这是新内容\n";
$handle = fopen('output.txt', 'w');
if ($handle) {
$bytes_written = fwrite($handle, $content);
if ($bytes_written === false) {
echo "写入失败";
} else {
echo "成功写入 $bytes_written 字节";
}
fclose($handle);
}
2. 追加写入文件
用a模式追加内容,不影响原有数据:
$log = "[" . date('Y-m-d H:i:s') . "] 新日志\n";
$handle = fopen('app.log', 'a');
fwrite($handle, $log);
fclose($handle);
3. 简化写入:file_put_contents()
一行代码完成写入,支持追加参数:
// 覆盖写入
file_put_contents('test.txt', '覆盖内容', LOCK_EX);
// 追加写入
file_put_contents('test.txt', '追加内容', FILE_APPEND);
三、实战场景:常见文件读写应用
1. 日志记录系统
每天生成独立日志文件,按日期命名并追加写入:
$logDir = 'logs/';
$logFile = $logDir . date('Ymd') . '.log';
// 确保日志目录存在
if (!file_exists($logDir)) {
mkdir($logDir, 0755, true);
}
// 写入日志
$logMessage = "用户登录成功:IP=" . $_SERVER['REMOTE_ADDR'] . "\n";
file_put_contents($logFile, $logMessage, FILE_APPEND);
2. 配置文件管理
读取自定义配置文件(如config.ini)并解析:
// 读取配置文件
$config = parse_ini_file('config.ini', true); // true表示返回多维数组
if ($config) {
echo "数据库地址:" . $config['db']['host'];
}
// 更新配置文件
$newConfig = ['db' => ['host' => '192.168.1.1', 'port' => 3306]];
file_put_contents('config.ini', parse_ini_array($newConfig, true));
3. CSV文件处理
读取CSV数据并转换为数组:
// 读取CSV
$csvData = [];
$handle = fopen('data.csv', 'r');
while (($row = fgetcsv($handle)) !== false) {
$csvData[] = $row;
}
fclose($handle);
// 写入CSV
$newRow = ['ID' => 1, 'Name' => '测试', 'Score' => 95];
$handle = fopen('data.csv', 'a');
fputcsv($handle, $newRow);
fclose($handle);
四、进阶技巧:性能与安全优化
1. 大文件处理:分块读取
处理GB级大文件时,避免一次性加载到内存:
$handle = fopen('large_file.txt', 'r');
$bufferSize = 4096; // 4KB块
while (!feof($handle)) {
$chunk = fread($handle, $bufferSize);
processChunk($chunk); // 处理数据块
}
fclose($handle);
2. 异常处理与错误捕获
使用try-catch捕获文件操作异常:
try {
$content = file_get_contents('critical.txt');
if ($content === false) {
throw new Exception("文件读取失败");
}
} catch (Exception $e) {
error_log("文件操作错误:" . $e->getMessage());
// 记录错误日志后可返回友好提示
}
3. 安全防护:防止路径遍历
验证文件路径,避免恶意路径:
$userInput = $_GET['file'];
$validPath = realpath('files/' . basename($userInput)); // 过滤路径
if ($validPath && strpos($validPath, realpath('files')) === 0) {
readfile($validPath);
} else {
die("非法文件访问");
}
五、总结与注意事项
PHP文件读写需注意以下关键点:
- 资源释放:无论成功失败,使用
fclose()关闭文件句柄,或用try-finally确保释放。 - 异常处理:始终检查文件打开/读写失败的情况,避免程序崩溃。
- 权限控制:目录和文件权限需设置合理(如Linux下
0755目录,0644文件)。 - 安全过滤:严格验证文件路径,防止路径遍历攻击,避免直接拼接用户输入。
通过本文掌握基础读写操作后,可进一步结合数据库、缓存等技术,实现更复杂的数据处理需求。
文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

