php fwrite() 写中文乱码本质是编码不一致:脚本utf-8但文件被gbk编辑器打开;file_put_contents()无需file_text(不存在该常量);csv需加bom头\ufeff;cli乱码需匹配终端编码。

PHP fwrite() 写入中文显示乱码,先看文件保存编码
乱码本质是写入时用的编码和文件实际保存的编码不一致。PHP 脚本本身如果是 UTF-8 编码(无 BOM),但用 fwrite() 直接写字符串,不会自动转码——它只管把内存里的字节原样写进去。如果编辑器默认用 GBK 打开这个文件,UTF-8 字节流就被错解了。
- 确认 PHP 源文件编码:用 VS Code / Sublime 看右下角,必须是
UTF-8(不含 BOM) - 确认目标文件被什么编码打开:不是“PHP 怎么写”,而是“你用什么软件打开它”。记事本默认用系统 ANSI(Windows 下常为 GBK),会把 UTF-8 写的中文全显示成乱码
- 临时验证方法:用浏览器直接打开生成的 .txt 文件,右键 → 编码 → 选
UTF-8,如果中文正常,说明写入没问题,只是打开方式错了
PHP file_put_contents() 写中文前必须指定 FILE_TEXT?
不用。PHP 没有 FILE_TEXT 这个常量,那是干扰项。真正影响编码的是你传进去的字符串本身的字节序列,以及是否在写入前做了编码转换。
-
file_put_contents('a.txt', '你好')—— 如果脚本是 UTF-8 编码,这行就写入 UTF-8 字节,没问题 - 如果源数据来自数据库或表单,且是 GBK 编码,得先转:
iconv('GBK', 'UTF-8', $str)或mb_convert_encoding($str, 'UTF-8', 'GBK') - 避免用
file_put_contents('a.txt', '你好', FILE_APPEND | LOCK_EX)后发现乱码——问题不在标志位,而在前面字符串来源是否统一为 UTF-8
header() 输出 CSV 中文,Excel 打开还是乱码?
这是经典陷阱:HTTP 响应头声明了 UTF-8,但 Excel(尤其 Windows 版)根本不认。它默认按本地 ANSI 解析 CSV,导致 UTF-8 字节被当 GBK 解,首字节就错。
- 解决办法不是改 PHP 编码,而是加 BOM 头:
$content = "\xEF\xBB\xBF" . "姓名,城市\n张三,北京"; file_put_contents('data.csv', $content); - 不要用
header('Content-Type: text/csv; charset=utf-8');试图让 Excel 醒悟——它忽略这个 - 如果数据来自 MySQL,确保连接层也用 UTF-8:
mysqli_set_charset($conn, 'utf8mb4'),否则查出来的字段可能已是乱码字节
PHP CLI 模式下写文件中文乱码,和终端编码强相关
Web 环境下浏览器可指定编码,CLI 下终端(cmd、PowerShell、iTerm)有自己的默认代码页,PHP 不干预,只输出原始字节。
立即学习“PHP免费学习笔记(深入)”;
- Windows cmd 默认是
GBK(chcp 936),但你的 PHP 脚本是 UTF-8,直接echo "中文"或fwrite()写进去,终端显示就乱 - 临时修复:运行前执行
chcp 65001切到 UTF-8 模式(但部分旧程序不兼容) - 更稳做法:写文件时不做任何假设,明确转换:
$str = mb_convert_encoding($str, 'GBK', 'UTF-8'); fwrite($fp, $str);(仅当你确定目标环境是 GBK 时) - Linux/macOS 终端通常默认 UTF-8,但若 locale 是
zh_CN.GBK,同样会出问题——统一设为en_US.UTF-8或检查locale输出
最麻烦的不是 PHP 写不对,而是你手里同时存在 UTF-8 脚本、GBK 数据库、ANSI 终端、带 BOM 的编辑器、无 BOM 的 IDE——每个环节都可能悄悄转一次码。盯住源头编码、中间传输、最终消费三方是否对齐,比找某个“万能函数”有用得多。











