file() 函数是PHP中用于将整个文件读入数组的内置函数。它读取文件的每一行,并将每一行作为数组的一个元素。这个函数非常适合读取配置文件、日志文件等需要逐行处理的情况。
语法
array file ( string $filename [, int $flags = 0 [, resource $context ]] )
参数说明
| 参数 | 描述 | 是否必需 | 默认值 |
|---|---|---|---|
| filename | 要读取的文件路径 | 是 | - |
| flags | 可选。可以使用以下一个或多个常量:
|
否 | 0 |
| context | 可选。文件上下文资源,由stream_context_create()创建 | 否 | null |
返回值
- 成功时返回包含文件行的数组。
- 失败时返回 FALSE。
- 数组的每个元素对应文件中的一行,包括换行符(除非使用
FILE_IGNORE_NEW_LINES标志)。
注意事项
- file()函数会将整个文件加载到内存中,因此不适合处理非常大的文件。
- 每行末尾的换行符会保留,除非使用
FILE_IGNORE_NEW_LINES标志。 - 如果文件不存在或无法读取,函数会返回FALSE并生成一个
E_WARNING级别的错误。 - 可以使用
@错误控制运算符来抑制错误信息。
示例代码
示例1:基本使用 - 读取文件到数组
<?php
// 读取文件,每行作为数组的一个元素
$lines = file('data.txt');
if ($lines !== false) {
foreach ($lines as $line_num => $line) {
echo "行 #{$line_num} : " . htmlspecialchars($line) . "<br>\n";
}
} else {
echo "无法读取文件";
}
?>
示例2:使用标志参数
<?php
// 读取文件,忽略换行符并跳过空行
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines !== false) {
echo "文件共有 " . count($lines) . " 行非空内容:<br>\n";
foreach ($lines as $line) {
echo htmlspecialchars($line) . "<br>\n";
}
}
?>
示例3:处理大文件的替代方案
注意:file()会将整个文件加载到内存,对于大文件建议使用fgets()逐行读取。
<?php
// 使用file() - 适合小文件
function readSmallFile($filename) {
return file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
}
// 使用fgets()逐行读取 - 适合大文件
function readLargeFile($filename) {
$lines = [];
$file = fopen($filename, 'r');
if ($file) {
while (($line = fgets($file)) !== false) {
$line = rtrim($line); // 移除换行符
if ($line !== '') {
$lines[] = $line;
}
}
fclose($file);
}
return $lines;
}
// 根据文件大小选择方法
$filename = 'data.txt';
if (filesize($filename) < 1024 * 1024) { // 小于1MB
$lines = readSmallFile($filename);
} else {
$lines = readLargeFile($filename);
}
echo "读取了 " . count($lines) . " 行数据";
?>
示例4:读取CSV文件
<?php
// 读取CSV文件并解析每行
$csv_lines = file('data.csv', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$data = [];
if ($csv_lines !== false) {
foreach ($csv_lines as $line) {
// 将CSV行拆分为数组
$row = str_getcsv($line);
$data[] = $row;
}
}
echo "<pre>";
print_r($data);
echo "</pre>";
?>
示例5:读取远程文件
<?php
// 使用stream_context_create创建上下文
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => "User-Agent: MyPHPApp\r\n"
]
]);
// 读取远程文件
$url = 'https://example.com/data.txt';
$lines = @file($url, FILE_IGNORE_NEW_LINES, $context);
if ($lines !== false) {
echo "从远程URL读取了 " . count($lines) . " 行数据";
} else {
echo "无法读取远程文件";
}
?>
示例6:读取INI配置文件
<?php
// 读取配置文件
$config_lines = file('config.ini', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$config = [];
if ($config_lines !== false) {
foreach ($config_lines as $line) {
// 跳过注释行
if (strpos(trim($line), ';') === 0 || strpos(trim($line), '#') === 0) {
continue;
}
// 解析键值对
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$config[trim($key)] = trim($value);
}
}
}
echo "数据库主机: " . ($config['db_host'] ?? '未设置');
?>
与类似函数的比较
| 函数 | 描述 | 适用场景 |
|---|---|---|
file() |
将整个文件读入数组 | 小文件、配置文件、需要随机访问行 |
file_get_contents() |
将整个文件读入字符串 | 小文件、需要整体处理的内容 |
fgets() |
逐行读取文件 | 大文件、内存敏感的场景 |
readfile() |
读取文件并输出到缓冲区 | 直接输出文件内容到浏览器 |
性能优化建议
最佳实践
- 对于小于1MB的文件,使用
file()是合适的。 - 对于大文件,使用
fgets()逐行读取。 - 使用
FILE_IGNORE_NEW_LINES标志可以避免后续处理换行符。 - 读取远程文件时,设置适当的超时和上下文选项。
- 使用
@file()抑制错误,但更好的做法是检查文件是否存在和可读。
完整示例:安全地读取文件
<?php
function safeFileRead($filename, $flags = 0) {
// 检查文件是否存在
if (!file_exists($filename)) {
throw new Exception("文件不存在: $filename");
}
// 检查文件是否可读
if (!is_readable($filename)) {
throw new Exception("文件不可读: $filename");
}
// 检查文件大小(限制为10MB)
$max_size = 10 * 1024 * 1024; // 10MB
if (filesize($filename) > $max_size) {
throw new Exception("文件过大,最大支持10MB");
}
// 读取文件
$content = file($filename, $flags);
if ($content === false) {
throw new Exception("读取文件失败: $filename");
}
return $content;
}
// 使用示例
try {
$lines = safeFileRead('data.txt', FILE_IGNORE_NEW_LINES);
echo "成功读取 " . count($lines) . " 行数据";
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>