10. 文件操作和IO流

基本I/O流

1. 标准输入输出流

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <iomanip>

// 基本输出
std::cout << "Hello" << std::endl;
std::cout << "Value: " << 42 << "\n";

// 格式化输出
std::cout << std::fixed << std::setprecision(2);
std::cout << "Pi: " << 3.14159265359 << "\n";  // 输出:3.14

std::cout << std::setw(10) << std::right << "Right"
          << std::setw(10) << std::left << "Left" << "\n";

// 基本输入
int n;
std::cout << "Enter a number: ";
std::cin >> n;

// 输入字符串
std::string name;
std::cout << "Enter your name: ";
std::getline(std::cin, name);

// 错误处理
if (std::cin.fail()) {
    std::cin.clear();  // 清除错误状态
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // 清空输入缓冲区
}

2. 流操纵算子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <iomanip>

// 数值格式
std::cout << std::hex << 255 << "\n";     // 十六进制:ff
std::cout << std::oct << 255 << "\n";     // 八进制:377
std::cout << std::dec << 255 << "\n";     // 十进制:255

// 浮点数格式
std::cout << std::scientific << 1234.5678 << "\n";  // 1.234568e+03
std::cout << std::fixed << 1234.5678 << "\n";      // 1234.567800

// 字段宽度和对齐
std::cout << std::setw(10) << std::right << "Right" << "\n";
std::cout << std::setw(10) << std::left << "Left" << "\n";
std::cout << std::setfill('*') << std::setw(10) << "Fill" << "\n";

// 布尔值格式
std::cout << std::boolalpha << true << "\n";      // true
std::cout << std::noboolalpha << true << "\n";    // 1

文件操作

1. 文本文件操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <fstream>
#include <string>

// 写入文件
void writeTextFile() {
    std::ofstream outFile("example.txt");
    if (outFile.is_open()) {
        outFile << "Hello, File I/O!" << "\n";
        outFile << 42 << "\n";
        outFile.close();
    }
}

// 读取文件
void readTextFile() {
    std::ifstream inFile("example.txt");
    if (inFile.is_open()) {
        std::string line;
        while (std::getline(inFile, line)) {
            std::cout << line << "\n";
        }
        inFile.close();
    }
}

// 追加到文件
void appendToFile() {
    std::ofstream outFile("example.txt", std::ios::app);
    if (outFile.is_open()) {
        outFile << "Appended text" << "\n";
        outFile.close();
    }
}

// 检查文件状态
void checkFileStatus() {
    std::ifstream file("example.txt");
    if (!file) {
        std::cerr << "Error opening file\n";
        return;
    }
    
    if (file.eof()) {
        std::cout << "End of file reached\n";
    }
    
    if (file.bad()) {
        std::cout << "Bad bit set (fatal error)\n";
    }
    
    if (file.fail()) {
        std::cout << "Fail bit set (non-fatal error)\n";
    }
}

2. 二进制文件操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <fstream>

struct Record {
    int id;
    char name[50];
    double score;
};

// 写入二进制文件
void writeBinaryFile() {
    std::ofstream outFile("data.bin", std::ios::binary);
    if (outFile.is_open()) {
        Record record = {1, "John", 95.5};
        outFile.write(reinterpret_cast<char*>(&record), sizeof(Record));
        outFile.close();
    }
}

// 读取二进制文件
void readBinaryFile() {
    std::ifstream inFile("data.bin", std::ios::binary);
    if (inFile.is_open()) {
        Record record;
        inFile.read(reinterpret_cast<char*>(&record), sizeof(Record));
        std::cout << "ID: " << record.id << "\n"
                  << "Name: " << record.name << "\n"
                  << "Score: " << record.score << "\n";
        inFile.close();
    }
}

// 随机访问
void randomAccess() {
    std::fstream file("data.bin", std::ios::in | std::ios::out | std::ios::binary);
    if (file.is_open()) {
        // 移动到第二条记录
        file.seekg(sizeof(Record), std::ios::beg);
        
        Record record;
        file.read(reinterpret_cast<char*>(&record), sizeof(Record));
        
        // 移动到文件末尾
        file.seekp(0, std::ios::end);
        file.close();
    }
}

字符串流

1. 字符串输入流

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <sstream>

// 解析字符串
void parseString() {
    std::string data = "123 45.67 Hello";
    std::istringstream iss(data);
    
    int i;
    double d;
    std::string s;
    
    iss >> i >> d >> s;
    
    std::cout << "Integer: " << i << "\n"
              << "Double: " << d << "\n"
              << "String: " << s << "\n";
}

// 按行解析CSV
void parseCSV() {
    std::string csvLine = "John,25,New York";
    std::istringstream iss(csvLine);
    std::string token;
    
    while (std::getline(iss, token, ',')) {
        std::cout << token << "\n";
    }
}

2. 字符串输出流

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <sstream>

// 构建字符串
void buildString() {
    std::ostringstream oss;
    oss << "Integer: " << 42 << "\n"
        << "Double: " << 3.14 << "\n"
        << "String: " << "Hello";
    
    std::string result = oss.str();
    std::cout << result;
}

// 格式化输出到字符串
void formatToString() {
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(2);
    oss << "Price: $" << 99.99;
    std::string formatted = oss.str();
}

高级I/O操作

1. 自定义流操纵算子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 自定义流操纵算子
std::ostream& currency(std::ostream& os) {
    os << "$";
    return os;
}

// 带参数的流操纵算子
class setprecision_currency {
    int precision;
public:
    setprecision_currency(int p) : precision(p) {}
    friend std::ostream& operator<<(std::ostream& os, const setprecision_currency& pc) {
        os << std::fixed << std::setprecision(pc.precision);
        return os;
    }
};

// 使用示例
void useCustomManipulators() {
    double price = 99.99;
    std::cout << currency << setprecision_currency(2) << price << "\n";
}

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <filesystem>
namespace fs = std::filesystem;

void fileSystemOperations() {
    // 创建目录
    fs::create_directory("example_dir");
    
    // 复制文件
    fs::copy_file("source.txt", "dest.txt", fs::copy_options::overwrite_existing);
    
    // 遍历目录
    for (const auto& entry : fs::directory_iterator("example_dir")) {
        std::cout << entry.path() << "\n";
    }
    
    // 文件信息
    fs::path p = "example.txt";
    if (fs::exists(p)) {
        std::cout << "File size: " << fs::file_size(p) << "\n"
                  << "Last write time: " << fs::last_write_time(p) << "\n";
    }
    
    // 路径操作
    fs::path filePath = "dir/subdir/file.txt";
    std::cout << "Extension: " << filePath.extension() << "\n"
              << "Filename: " << filePath.filename() << "\n"
              << "Parent path: " << filePath.parent_path() << "\n";
}

3. 错误处理和异常

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void errorHandling() {
    try {
        std::ifstream file("nonexistent.txt");
        if (!file) {
            throw std::runtime_error("Could not open file");
        }
        
        // 文件操作...
        
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
    }
    
    // 使用异常掩码
    std::ifstream file;
    file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    
    try {
        file.open("example.txt");
        // 文件操作...
        file.close();
    } catch (const std::ios_base::failure& e) {
        std::cerr << "I/O error: " << e.what() << "\n";
    }
}

57.12k 字
43篇文章