ifstream默认不抛异常,需检查is_open()或failbit;写入中文乱码主因是locale与文件编码不匹配,推荐wofstream配codecvt_utf8;二进制读写应避免eof(),改用read()和gcount()。

ifstream 打开文件失败却不报错?检查 failbit 和 is_open()
默认情况下,ifstream 构造或 open() 失败不会抛异常,对象进入失效状态但不崩溃。常见现象是后续 getline() 或 >> 读不出内容,变量值还是初始值。
- 务必在打开后检查:
if (!fin.is_open())或if (fin.fail()) - 更稳妥的做法是启用异常位:
fin.exceptions(ifstream::failbit | ifstream::badbit);,这样失败会直接抛std::ios_base::failure - 路径含中文或空格时,Windows 下建议用 UTF-8 编码源文件 +
std::locale::global(std::locale(""));(仅限本地环境),否则可能因编码不匹配打不开
ofstream 写入中文乱码?别只盯着 setf(ios::unitbuf)
乱码主因不是缓冲区,而是流的 locale 和文件实际编码不一致。VS 默认窄字符流用系统 ANSI(如 GBK),而源文件常为 UTF-8,写入字节流后用 UTF-8 编辑器打开就显示乱码。
- 若需写 UTF-8 文本,**不要**用
ofstream直接写std::string中文——它只是按字节转发,不转码 - 简单方案:用
std::wofstream+std::locale绑定 UTF-8 facet(需 C++11 以上):std::wofstream wout("out.txt"); wout.imbue(std::locale(wout.getloc(), new std::codecvt_utf8)); wout << L"你好"; - 跨平台稳妥做法:手动将 UTF-8 字符串(
std::string)以二进制方式写入,确保编辑器用 UTF-8 解码——此时不用改 locale,但必须用ofstream("xxx", ios::binary)
读写同一文件用 fstream 时,seekg() 和 seekp() 要分开调
fstream 同时维护输入位置(get pointer)和输出位置(put pointer),二者独立。混用 read() 和 write() 时,不显式重定位会导致读写错位。
- 写完立即读,必须先
seekg(0)回开头;读完想追加写,得seekp(0, ios::end) - 使用
ios::in | ios::out模式打开时,文件必须已存在(ios::trunc会清空,ios::app会强制写末尾,不支持随机读写) - 若需读写+创建文件,推荐分两步:先用
ofstream创建并写,再用ifstream读;或用fstream加ios::in | ios::out | ios::ate,然后手动seekg(0)
大文件循环读取卡死?别用 while (!fin.eof())
eof() 只在**尝试读取失败后**才返回 true,循环体末尾检测会导致多执行一次无效读取,甚至使 fin 进入 failbit 状态,后续操作全部失效。
立即学习“C++免费学习笔记(深入)”;
- 正确写法是把读取动作作为 while 条件:
while (getline(fin, line)) { ... }或while (fin >> value) { ... } - 对二进制大文件,优先用
read()配合gcount()判断实际读取字节数,避免依赖eof() - 频繁小块读写影响性能,可手动设置缓冲区:
fin.rdbuf()->pubsetbuf(buffer, bufsize);(注意:必须在 open 前调用)
is_open() 返回 false 却不告诉你为什么,这时候看一眼 errno 或用 strerror(errno) 才能知道到底是 “No such file” 还是 “Permission denied”。











