Skip to content

C++ 文件和流

文件流概述

C++ 提供了三个主要的文件流类用于文件操作:

  • ifstream - 输入文件流(从文件读取)
  • ofstream - 输出文件流(写入文件)
  • fstream - 文件流(读写操作)

基本文件操作

打开文件

cpp
#include <fstream>
#include <iostream>

int main() {
    // 方法1: 构造函数
    std::ofstream outfile1("example.txt");
    
    // 方法2: open() 函数
    std::ofstream outfile2;
    outfile2.open("example.txt");
    
    return 0;
}

打开模式

cpp
// in - 以读取模式打开
std::ifstream file("data.txt", std::ios::in);

// out - 以写入模式打开
std::ofstream file("data.txt", std::ios::out);

// app - 追加模式
std::ofstream file("data.txt", std::ios::app);

// ate - 定位到文件末尾
std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::ate);

// trunc - 截断文件(删除内容)
std::ofstream file("data.txt", std::ios::out | std::ios::trunc);

// binary - 二进制模式
std::ofstream file("data.bin", std::ios::out | std::ios::binary);

检查文件状态

cpp
std::ifstream file("data.txt");

if (!file.is_open()) {
    std::cerr << "Error opening file!" << std::endl;
    return 1;
}

if (file.good()) {
    std::cout << "File stream is good" << std::endl;
}

if (file.eof()) {
    std::cout << "End of file reached" << std::endl;
}

写入文件

写入文本

cpp
#include <fstream>
#include <iostream>

int main() {
    std::ofstream outfile("output.txt");
    
    if (!outfile.is_open()) {
        std::cerr << "Error opening file!" << std::endl;
        return 1;
    }
    
    // 使用 << 运算符
    outfile << "Hello, World!" << std::endl;
    outfile << "This is C++ file writing." << std::endl;
    
    // 写入变量
    int number = 42;
    double pi = 3.14159;
    outfile << "Number: " << number << std::endl;
    outfile << "Pi: " << pi << std::endl;
    
    outfile.close();
    return 0;
}

格式化输出

cpp
std::ofstream outfile("formatted.txt");

// 设置宽度
outfile << std::setw(10) << "Name" << std::setw(10) << "Age" << std::endl;
outfile << std::setw(10) << "John" << std::setw(10) << 25 << std::endl;

// 精度控制
outfile << std::fixed << std::setprecision(2) << 3.14159 << std::endl;

// 填充字符
outfile << std::setfill('-') << std::setw(10) << "Test" << std::endl;

读取文件

逐行读取

cpp
#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("input.txt");
    
    if (!infile.is_open()) {
        std::cerr << "Error opening file!" << std::endl;
        return 1;
    }
    
    std::string line;
    int line_number = 0;
    
    while (std::getline(infile, line)) {
        line_number++;
        std::cout << "Line " << line_number << ": " << line << std::endl;
    }
    
    infile.close();
    return 0;
}

逐词读取

cpp
std::ifstream infile("input.txt");
std::string word;

while (infile >> word) {
    std::cout << word << std::endl;
}

读取数值

cpp
std::ifstream infile("numbers.txt");
int number;

while (infile >> number) {
    std::cout << "Read: " << number << std::endl;
}

读取结构化数据

cpp
struct Person {
    std::string name;
    int age;
    double salary;
};

std::ifstream infile("people.txt");
Person p;

while (infile >> p.name >> p.age >> p.salary) {
    std::cout << p.name << " - Age: " << p.age 
              << ", Salary: " << p.salary << std::endl;
}

文件定位

获取当前位置

cpp
std::ifstream infile("data.txt");

// 获取读取位置
std::streampos pos = infile.tellg();
std::cout << "Current position: " << pos << std::endl;

设置位置

cpp
std::ifstream infile("data.txt");

// 绝对定位
infile.seekg(0, std::ios::beg);  // 文件开头
infile.seekg(0, std::ios::end);  // 文件末尾
infile.seekg(100);               // 第100个字节

// 相对定位
infile.seekg(50, std::ios::cur); // 从当前位置向前移动50字节
infile.seekg(-50, std::ios::cur); // 从当前位置向后移动50字节

获取文件大小

cpp
std::ifstream infile("data.txt", std::ios::binary | std::ios::ate);
std::streamsize size = infile.tellg();

std::cout << "File size: " << size << " bytes" << std::endl;

二进制文件操作

写入二进制数据

cpp
#include <fstream>
#include <vector>

struct Data {
    int id;
    double value;
    char name[20];
};

int main() {
    Data data = {1, 3.14159, "Binary Data"};
    
    std::ofstream outfile("data.bin", std::ios::binary);
    
    // 写入单个对象
    outfile.write(reinterpret_cast<char*>(&data), sizeof(Data));
    
    // 写入数组
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    outfile.write(reinterpret_cast<char*>(numbers.data()), 
                 numbers.size() * sizeof(int));
    
    outfile.close();
    return 0;
}

读取二进制数据

cpp
#include <fstream>
#include <vector>

struct Data {
    int id;
    double value;
    char name[20];
};

int main() {
    std::ifstream infile("data.bin", std::ios::binary);
    
    // 读取单个对象
    Data data;
    infile.read(reinterpret_cast<char*>(&data), sizeof(Data));
    
    std::cout << "ID: " << data.id << std::endl;
    std::cout << "Value: " << data.value << std::endl;
    std::cout << "Name: " << data.name << std::endl;
    
    // 读取数组
    std::vector<int> numbers(5);
    infile.read(reinterpret_cast<char*>(numbers.data()), 
               numbers.size() * sizeof(int));
    
    infile.close();
    return 0;
}

错误处理

检查错误状态

cpp
std::ifstream file("data.txt");

if (file.fail()) {
    std::cerr << "Error occurred!" << std::endl;
}

if (file.bad()) {
    std::cerr << "Critical error occurred!" << std::endl;
}

清除错误状态

cpp
std::ifstream file("data.txt");

if (file.fail()) {
    file.clear();  // 清除错误状态
    file.seekg(0, std::ios::beg);  // 重置文件位置
}

异常处理

cpp
std::ifstream file("data.txt");
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);

try {
    // 文件操作
    std::string line;
    std::getline(file, line);
} catch (const std::ifstream::failure& e) {
    std::cerr << "Exception opening/reading file: " << e.what() << std::endl;
}

文件操作示例

复制文件

cpp
#include <fstream>

bool copyFile(const std::string& source, const std::string& dest) {
    std::ifstream src(source, std::ios::binary);
    std::ofstream dst(dest, std::ios::binary);
    
    if (!src.is_open() || !dst.is_open()) {
        return false;
    }
    
    dst << src.rdbuf();
    return true;
}

读取配置文件

cpp
#include <fstream>
#include <map>
#include <sstream>

std::map<std::string, std::string> readConfig(const std::string& filename) {
    std::map<std::string, std::string> config;
    std::ifstream file(filename);
    
    std::string line;
    while (std::getline(file, line)) {
        if (line.empty() || line[0] == '#') continue;
        
        size_t pos = line.find('=');
        if (pos != std::string::npos) {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);
            config[key] = value;
        }
    }
    
    return config;
}

统计文件信息

cpp
#include <fstream>

void countFileStats(const std::string& filename) {
    std::ifstream file(filename);
    
    int lines = 0, words = 0, chars = 0;
    std::string word;
    
    while (file >> word) {
        words++;
        chars += word.length();
    }
    
    file.clear();
    file.seekg(0, std::ios::beg);
    
    std::string line;
    while (std::getline(file, line)) {
        lines++;
    }
    
    std::cout << "Lines: " << lines << std::endl;
    std::cout << "Words: " << words << std::endl;
    std::cout << "Characters: " << chars << std::endl;
}

最佳实践

RAII 模式

cpp
#include <fstream>
#include <string>

void processFile(const std::string& filename) {
    std::ifstream file(filename);  // 自动在作用域结束时关闭
    
    if (!file.is_open()) {
        return;
    }
    
    // 文件操作
}

资源管理

cpp
#include <fstream>
#include <memory>

void safeFileOperation(const std::string& filename) {
    std::unique_ptr<std::ifstream> file = 
        std::make_unique<std::ifstream>(filename);
    
    if (!file->is_open()) {
        throw std::runtime_error("Failed to open file");
    }
    
    // 文件操作
    // 文件在 unique_ptr 销毁时自动关闭
}

临时文件

cpp
#include <fstream>
#include <cstdio>

void useTempFile() {
    // 创建临时文件
    std::FILE* tmp = std::tmpfile();
    if (tmp) {
        std::fprintf(tmp, "Temporary data\n");
        std::rewind(tmp);  // 重置文件指针
        
        char buffer[256];
        while (std::fgets(buffer, sizeof(buffer), tmp)) {
            std::cout << buffer;
        }
        
        std::fclose(tmp);  // 文件自动删除
    }
}

文件系统操作(C++17)

cpp
#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void fileSystemOperations() {
    // 检查文件是否存在
    if (fs::exists("test.txt")) {
        std::cout << "File exists" << std::endl;
    }
    
    // 获取文件大小
    if (fs::is_regular_file("test.txt")) {
        auto size = fs::file_size("test.txt");
        std::cout << "File size: " << size << " bytes" << std::endl;
    }
    
    // 复制文件
    fs::copy_file("source.txt", "destination.txt");
    
    // 删除文件
    fs::remove("old_file.txt");
    
    // 创建目录
    fs::create_directory("new_folder");
    
    // 遍历目录
    for (const auto& entry : fs::directory_iterator(".")) {
        std::cout << entry.path() << std::endl;
    }
}

总结

  • ifstream: 用于读取文件
  • ofstream: 用于写入文件
  • fstream: 用于读写操作
  • 使用适当的打开模式
  • 始终检查文件操作状态
  • 使用 RAII 确保资源正确释放
  • C++17 提供了 filesystem 库用于文件系统操作

相关教程

Content is for learning and research only.