17370845950

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

ifstream 打开文件失败却不报错?检查 failbitis_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 读;或用 fstreamios::in | ios::out | ios::ate,然后手动 seekg(0)

大文件循环读取卡死?别用 while (!fin.eof())

eof() 只在**尝试读取失败后**才返回 true,循环体末尾检测会导致多执行一次无效读取,甚至使 fin 进入 failbit 状态,后续操作全部失效。

  • 正确写法是把读取动作作为 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”。