c++文件操作详解
C++ 提供了强大的文件操作功能,主要通过 <fstream>
头文件中的类来实现。以下是对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 <fstream>// 方式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 引入了 <filesystem>
头文件,提供了更高级的文件操作功能:
#include <filesystem>
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 <windows.h>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 <cstdio>// 创建临时文件
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); // 手动删除
九、错误处理与最佳实践
- 始终检查文件操作结果
if (!file) {// 处理错误}
- 使用RAII管理资源
{std::ofstream file("data.txt");// 使用文件...
} // 文件自动关闭
- 处理大文件
#ifdef _WIN32// Windows 上处理大于2GB的文件std::ifstream bigFile("large.bin", std::ios::binary | std::ios::ate);bigFile.seekg(0, std::ios::beg);#endif
- 跨平台路径处理
// 使用C++17文件系统fs::path filePath = "data";filePath /= "subdir";filePath /= "file.txt";// 输出平台无关路径std::cout << "Path: " << filePath.generic_string() << std::endl;
- 异常处理
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;}
十、性能优化建议
- 使用缓冲区:
char buffer[4096];std::ifstream inFile("large.bin", std::ios::binary);while (inFile.read(buffer, sizeof(buffer))) {// 处理缓冲区数据}
- 减少文件打开/关闭次数:
- 批量处理文件操作
- 复用文件流对象
- 使用内存映射处理大文件:
- 避免多次读写操作
- 提供随机访问能力
- 异步文件I/O:
#include <future>auto readFuture = std::async(std::launch::async, []{std::ifstream file("data.bin", std::ios::binary);// 读取操作...});// 主线程继续执行其他任务...readFuture.get(); // 等待读取完成
-
选择合适的打开模式:
- 二进制模式避免文本转换开销
- 追加模式减少文件定位开销
总结
C++提供了丰富的文件操作功能:
- 基础文本和二进制文件读写
- 文件定位和状态管理
- C++17强大的文件系统库
- 高级技术如内存映射和异步I/O