string fread(resource $handle, int $length)
fread() 從文件指針讀取最多 $length 字節,遇到以下情況會停止:
$file = 'data.txt'; $fh = fopen($file, 'r'); $content = fread($fh, filesize($file)); fclose($fh);
問題:filesize() 返回值超過 memory_limit 時,一次性 fread() 會報錯。
解決:分塊讀寫
set_time_limit(0); // 移除執行時間限制
$source = 'large_file.bin';
$dest = 'copy.bin';
$rfp = fopen($source, 'rb');
$wfp = fopen($dest, 'wb');
while (!feof($rfp)) {
$chunk = fread($rfp, 1024 * 1024); // 每次 1MB
fwrite($wfp, $chunk);
}
fclose($rfp);
fclose($wfp);
echo "大文件拷貝完成";
PHP 7.0 及之前版本:fread() 純粹按字節讀取,完全不識別、不轉換編碼。
$handler = fopen('a.txt', 'rb'); // 二進制模式
$content = fread($handler, 1024);
echo $content; // 直接輸出字節流
顯示正常的前提:文件字節編碼 = PHP 腳本編碼 = HTML 頁面編碼 = 瀏覽器解碼編碼。任何一環不一致即產生亂碼。
現代解決方案:PHP 7.1+ 可用 mb_detect_encoding() 配合 mb_convert_encoding() 處理。
現象:
$size = filesize($file);
$handle = fopen($file, "rb"); // 二進制模式
while (!feof($handle)) {
var_dump(fread($handle, $size)); // 最後會多輸出一次空字符串
}
原因:Windows 文本文件結尾有 EOF 標記(Ctrl+Z / 0x1A),二進制模式會讀到此字節。
解決方案:
fopen($file, 'r') 文本模式 + fgets() 按行讀取feof() 前先檢查 fread() 返回值// 推薦寫法
$handle = fopen($file, 'r');
while (($line = fgets($handle)) !== false) {
// 處理每行
}
fclose($handle);
| 場景 | 推薦方式 |
|---|---|
| 小文件全讀 | file_get_contents() |
| 大文件流式處理 | fopen() + fread(8192) 循環 |
| 文本文件按行處理 | fopen('r') + fgets() |
| 二進制文件 | fopen('rb') + fread() |
| 編碼不確定文件 | 讀取後用 mb_detect_encoding() 檢測並轉碼 |