Skip to content

C++ 文件和流

C++ 提供了文件和流的功能,允许程序读取和写入文件。文件操作是程序与外部数据交互的重要方式。

1. 文件流的基本概念

C++ 提供了三种文件流类型:

  • std::ifstream:输入文件流,用于从文件读取数据
  • std::ofstream:输出文件流,用于向文件写入数据
  • std::fstream:文件流,既可以读取也可以写入

1.1 包含头文件

cpp
#include <fstream>
#include <iostream>

2. 写入文件

2.1 使用 ofstream 写入文件

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ofstream outfile("output.txt");
    
    if (outfile.is_open()) {
        outfile << "Hello, World!" << std::endl;
        outfile << "C++ Programming" << std::endl;
        outfile << "File I/O" << std::endl;
        
        outfile.close();
        std::cout << "文件写入成功" << std::endl;
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

2.2 追加写入文件

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ofstream outfile("output.txt", std::ios::app);
    
    if (outfile.is_open()) {
        outfile << "这是追加的内容" << std::endl;
        
        outfile.close();
        std::cout << "文件追加成功" << std::endl;
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

3. 读取文件

3.1 使用 ifstream 读取文件

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

int main() {
    std::ifstream infile("output.txt");
    
    if (infile.is_open()) {
        std::string line;
        while (std::getline(infile, line)) {
            std::cout << line << std::endl;
        }
        
        infile.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

3.2 逐字符读取文件

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ifstream infile("output.txt");
    
    if (infile.is_open()) {
        char ch;
        while (infile.get(ch)) {
            std::cout << ch;
        }
        
        infile.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

3.3 逐单词读取文件

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

int main() {
    std::ifstream infile("output.txt");
    
    if (infile.is_open()) {
        std::string word;
        while (infile >> word) {
            std::cout << word << std::endl;
        }
        
        infile.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

4. 文件打开模式

文件打开模式用于指定文件的打开方式。

模式描述
std::ios::in以读取方式打开文件
std::ios::out以写入方式打开文件
std::ios::app以追加方式打开文件
std::ios::ate打开文件并将文件指针移动到文件末尾
std::ios::trunc如果文件存在,则截断文件(清空内容)
std::ios::binary以二进制方式打开文件

4.1 使用文件打开模式

cpp
#include <iostream>
#include <fstream>

int main() {
    // 以写入方式打开文件
    std::ofstream outfile1("output1.txt", std::ios::out);
    
    // 以追加方式打开文件
    std::ofstream outfile2("output2.txt", std::ios::app);
    
    // 以读写方式打开文件
    std::fstream file("file.txt", std::ios::in | std::ios::out);
    
    return 0;
}

5. 文件指针

文件指针用于指定文件中的当前位置。

5.1 获取文件指针位置

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ofstream outfile("output.txt");
    
    if (outfile.is_open()) {
        outfile << "Hello, World!";
        
        // 获取文件指针位置
        std::streampos pos = outfile.tellp();
        std::cout << "文件指针位置: " << pos << std::endl;
        
        outfile.close();
    }
    
    return 0;
}

5.2 移动文件指针

cpp
#include <iostream>
#include <fstream>

int main() {
    std::fstream file("file.txt", std::ios::in | std::ios::out);
    
    if (file.is_open()) {
        file << "Hello, World!";
        
        // 移动文件指针到文件开头
        file.seekg(0, std::ios::beg);
        
        char ch;
        while (file.get(ch)) {
            std::cout << ch;
        }
        
        file.close();
    }
    
    return 0;
}

6. 二进制文件

6.1 写入二进制文件

cpp
#include <iostream>
#include <fstream>

struct Student {
    char name[50];
    int age;
    float gpa;
};

int main() {
    Student student = {"张三", 20, 3.8f};
    
    std::ofstream outfile("student.dat", std::ios::binary);
    
    if (outfile.is_open()) {
        outfile.write(reinterpret_cast<char*>(&student), sizeof(student));
        
        outfile.close();
        std::cout << "二进制文件写入成功" << std::endl;
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

6.2 读取二进制文件

cpp
#include <iostream>
#include <fstream>

struct Student {
    char name[50];
    int age;
    float gpa;
};

int main() {
    Student student;
    
    std::ifstream infile("student.dat", std::ios::binary);
    
    if (infile.is_open()) {
        infile.read(reinterpret_cast<char*>(&student), sizeof(student));
        
        std::cout << "姓名: " << student.name << std::endl;
        std::cout << "年龄: " << student.age << std::endl;
        std::cout << "GPA: " << student.gpa << std::endl;
        
        infile.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
    
    return 0;
}

7. 文件状态检查

7.1 检查文件状态

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ifstream infile("nonexistent.txt");
    
    if (!infile) {
        std::cout << "文件打开失败" << std::endl;
    }
    
    if (infile.is_open()) {
        std::cout << "文件已打开" << std::endl;
    } else {
        std::cout << "文件未打开" << std::endl;
    }
    
    if (infile.eof()) {
        std::cout << "已到达文件末尾" << std::endl;
    }
    
    if (infile.fail()) {
        std::cout << "文件操作失败" << std::endl;
    }
    
    if (infile.bad()) {
        std::cout << "文件发生严重错误" << std::endl;
    }
    
    return 0;
}

8. 示例:综合运用

现在,让我们看一个综合运用各种文件操作特性的例子:

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

struct Student {
    std::string name;
    int age;
    float gpa;
};

void write_students(const std::string& filename) {
    std::ofstream outfile(filename);
    
    if (outfile.is_open()) {
        Student students[] = {
            {"张三", 20, 3.8f},
            {"李四", 21, 3.5f},
            {"王五", 22, 3.9f}
        };
        
        for (const auto& student : students) {
            outfile << student.name << " " << student.age << " " << student.gpa << std::endl;
        }
        
        outfile.close();
        std::cout << "学生信息写入成功" << std::endl;
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
}

void read_students(const std::string& filename) {
    std::ifstream infile(filename);
    
    if (infile.is_open()) {
        std::string line;
        std::cout << "学生信息:" << std::endl;
        while (std::getline(infile, line)) {
            std::cout << line << std::endl;
        }
        
        infile.close();
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
}

void append_student(const std::string& filename, const Student& student) {
    std::ofstream outfile(filename, std::ios::app);
    
    if (outfile.is_open()) {
        outfile << student.name << " " << student.age << " " << student.gpa << std::endl;
        
        outfile.close();
        std::cout << "学生信息追加成功" << std::endl;
    } else {
        std::cout << "无法打开文件" << std::endl;
    }
}

int main() {
    std::string filename = "students.txt";
    
    // 写入学生信息
    write_students(filename);
    std::cout << std::endl;
    
    // 读取学生信息
    read_students(filename);
    std::cout << std::endl;
    
    // 追加学生信息
    Student new_student = {"赵六", 23, 3.7f};
    append_student(filename, new_student);
    std::cout << std::endl;
    
    // 再次读取学生信息
    read_students(filename);
    
    return 0;
}

小结

C++ 文件和流包括:

  1. 文件流的基本概念

    • std::ifstream:输入文件流,用于从文件读取数据
    • std::ofstream:输出文件流,用于向文件写入数据
    • std::fstream:文件流,既可以读取也可以写入
  2. 写入文件

    • 使用std::ofstream写入文件
    • 追加写入文件
  3. 读取文件

    • 使用std::ifstream读取文件
    • 逐行读取文件
    • 逐字符读取文件
    • 逐单词读取文件
  4. 文件打开模式

    • std::ios::in:以读取方式打开文件
    • std::ios::out:以写入方式打开文件
    • std::ios::app:以追加方式打开文件
    • std::ios::ate:打开文件并将文件指针移动到文件末尾
    • std::ios::trunc:如果文件存在,则截断文件(清空内容)
    • std::ios::binary:以二进制方式打开文件
  5. 文件指针

    • 获取文件指针位置:tellp()tellg()
    • 移动文件指针:seekp()seekg()
  6. 二进制文件

    • 写入二进制文件:write()
    • 读取二进制文件:read()
  7. 文件状态检查

    • 检查文件是否打开:is_open()
    • 检查文件是否到达末尾:eof()
    • 检查文件操作是否失败:fail()
    • 检查文件是否发生严重错误:bad()

关键概念:

  • 文件流:用于文件输入输出的流对象
  • 输入文件流std::ifstream,用于从文件读取数据
  • 输出文件流std::ofstream,用于向文件写入数据
  • 文件打开模式:指定文件的打开方式
  • 文件指针:指定文件中的当前位置
  • 二进制文件:以二进制方式存储的文件
  • 文件状态:表示文件操作的状态

掌握文件和流是编写 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的异常处理。