> 技术文档 > c++文件操作详解

c++文件操作详解

C++ 提供了强大的文件操作功能,主要通过  头文件中的类来实现。以下是对C++文件操作的全面解析:

一、文件流类体系

C++ 文件操作基于流的概念,核心类包括:

类名 描述 继承自 fstream 文件流(读写操作) iostream ifstream 输入文件流(读操作) istream ofstream 输出文件流(写操作) ostream filebuf 文件缓冲区 streambuf

二、文件打开模式

文件打开模式通过位掩码常量指定,可组合使用:

模式标志 描述 ios::in 打开文件进行读取(ifstream默认) ios::out 打开文件进行写入(ofstream默认),会截断现有文件 ios::app 追加模式,所有写入操作都在文件末尾进行 ios::ate 打开文件后定位到文件末尾 ios::trunc 如果文件存在,则截断文件(out模式默认启用) ios::binary 以二进制模式打开文件(避免文本转换) ios::nocreate 如果文件不存在,打开失败(非标准,建议用C++17文件系统) ios::noreplace 如果文件存在,打开失败(非标准)

三、文件基本操作

1. 打开文件

#include // 方式1:构造函数打开std::ofstream outFile(\"output.txt\", std::ios::out | std::ios::app);// 方式2:open()方法打开std::ifstream inFile;inFile.open(\"input.txt\", std::ios::in);// 检查文件是否成功打开if (!outFile.is_open()) { std::cerr << \"Error opening file!\" << std::endl; return 1;}

2. 关闭文件

outFile.close(); // 显式关闭文件inFile.close(); // 文件流析构时会自动关闭,但显式关闭是好习惯

3. 文件状态检查

if (inFile.fail()) { // 操作失败(如类型不匹配)}if (inFile.bad()) { // 严重错误(如磁盘故障)}if (inFile.eof()) { // 到达文件末尾}if (inFile.good()) { // 一切正常}// 重置错误状态inFile.clear();

四、文本文件操作

1. 写入文本文件

std::ofstream textOut(\"data.txt\");if (textOut) { textOut << \"Line 1: Hello, World!\\n\"; textOut << \"Line 2: The answer is \" << 42 << \"\\n\"; textOut << \"Line 3: Pi ≈ \" << 3.14159 << \"\\n\";}

2. 读取文本文件

std::ifstream textIn(\"data.txt\");if (textIn) { // 逐行读取 std::string line; while (std::getline(textIn, line)) { std::cout << line << std::endl; } // 重置文件指针到开头 textIn.clear(); textIn.seekg(0); // 按单词读取 std::string word; while (textIn >> word) { std::cout << word << \" \"; }}

五、二进制文件操作

1. 写入二进制数据

struct Record { int id; char name[50]; double balance;};Record records[3] = { {1, \"Alice\", 100.50}, {2, \"Bob\", 250.75}, {3, \"Charlie\", 500.25}};std::ofstream binOut(\"data.bin\", std::ios::binary);if (binOut) { binOut.write(reinterpret_cast<char*>(records), sizeof(records));}

2. 读取二进制数据

std::ifstream binIn(\"data.bin\", std::ios::binary);if (binIn) { // 获取文件大小 binIn.seekg(0, std::ios::end); size_t fileSize = binIn.tellg(); binIn.seekg(0, std::ios::beg); // 计算记录数量 size_t numRecords = fileSize / sizeof(Record); Record* readRecords = new Record[numRecords]; // 读取数据 binIn.read(reinterpret_cast<char*>(readRecords), fileSize); // 处理数据... delete[] readRecords;}

六、文件定位

std::fstream file(\"data.txt\", std::ios::in | std::ios::out);if (file) { // 获取当前位置 std::streampos pos = file.tellg(); // 移动到文件开头 file.seekg(0, std::ios::beg); // 移动到文件末尾 file.seekg(0, std::ios::end); // 向前移动10字节 file.seekg(10, std::ios::cur); // 向后移动5字节 file.seekg(-5, std::ios::cur); // 移动到第100字节处 file.seekg(100);}

七、C++17 文件系统库

C++17 引入了  头文件,提供了更高级的文件操作功能:

#include namespace fs = std::filesystem;// 创建目录fs::create_directory(\"data\");// 复制文件fs::copy_file(\"source.txt\", \"data/destination.txt\");// 检查文件属性if (fs::exists(\"data.txt\")) { std::cout << \"File size: \" << fs::file_size(\"data.txt\") << \" bytes\\n\"; std::cout << \"Last modified: \" << fs::last_write_time(\"data.txt\") << \"\\n\";}// 遍历目录for (const auto& entry : fs::directory_iterator(\".\")) { if (entry.is_regular_file()) { std::cout << \"File: \" << entry.path() << \"\\n\"; } else if (entry.is_directory()) { std::cout << \"Directory: \" << entry.path() << \"\\n\"; }}// 删除文件fs::remove(\"old_data.txt\");// 递归删除目录fs::remove_all(\"obsolete_data\");

八、高级文件操作技巧

1. 内存映射文件(平台特定)

// Windows 示例#include HANDLE hFile = CreateFile(\"large.bin\", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);char* data = (char*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);// 使用 data 指针访问文件内容...UnmapViewOfFile(data);CloseHandle(hMap);CloseHandle(hFile);

2. 临时文件处理

#include // 创建临时文件FILE* tmpFile = tmpfile();if (tmpFile) { fputs(\"Temporary data\", tmpFile); rewind(tmpFile); char buffer[256]; fgets(buffer, sizeof(buffer), tmpFile); std::cout << \"Temp content: \" << buffer << std::endl; fclose(tmpFile); // 自动删除}// 使用C++17文件系统auto tempPath = fs::temp_directory_path() / \"tempfile.tmp\";std::ofstream tempOut(tempPath);// 使用临时文件...fs::remove(tempPath); // 手动删除

九、错误处理与最佳实践

  1. 始终检查文件操作结果
if (!file) { // 处理错误 }
  1. 使用RAII管理资源
{std::ofstream file(\"data.txt\");// 使用文件...} // 文件自动关闭
  1. 处理大文件
 #ifdef _WIN32 // Windows 上处理大于2GB的文件 std::ifstream bigFile(\"large.bin\", std::ios::binary | std::ios::ate); bigFile.seekg(0, std::ios::beg); #endif
  1. 跨平台路径处理
// 使用C++17文件系统 fs::path filePath = \"data\"; filePath /= \"subdir\"; filePath /= \"file.txt\"; // 输出平台无关路径 std::cout << \"Path: \" << filePath.generic_string() << std::endl;
  1. 异常处理
std::ifstream file; file.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { file.open(\"important.txt\"); // 文件操作... } catch (const std::ios_base::failure& e) { std::cerr << \"File error: \" << e.what() << std::endl; }

十、性能优化建议

  1. 使用缓冲区
char buffer[4096]; std::ifstream inFile(\"large.bin\", std::ios::binary); while (inFile.read(buffer, sizeof(buffer))) { // 处理缓冲区数据 }
  1. 减少文件打开/关闭次数
    • 批量处理文件操作
    • 复用文件流对象
  2. 使用内存映射处理大文件
    • 避免多次读写操作
    • 提供随机访问能力
  3. 异步文件I/O
#include  auto readFuture = std::async(std::launch::async, []{ std::ifstream file(\"data.bin\", std::ios::binary); // 读取操作... }); // 主线程继续执行其他任务... readFuture.get(); // 等待读取完成
  1. 选择合适的打开模式

    • 二进制模式避免文本转换开销
    • 追加模式减少文件定位开销

总结

C++提供了丰富的文件操作功能:

  • 基础文本和二进制文件读写
  • 文件定位和状态管理
  • C++17强大的文件系统库
  • 高级技术如内存映射和异步I/O