C++ IO 与网络编程总结

✍️ Fer·📅 2026年8月20日·👁 4 次阅读
c++开发
📚 系列:现代 C++ 学习之路

一、C++ IO 流体系

⭐ IO 流继承体系

⭐ IO 流分类

分类输入类输出类读写类用途
标准流cincout / cerr / clog控制台 IO
文件流ifstreamofstreamfstream文件 IO
字符串流istringstreamostringstreamstringstream内存中字符串处理

二、文件 IO

⭐ 文件读写的基本操作

cpp
#include <fstream>
#include <string>

// 写文件
void WriteFile(const std::string& path) {
    std::ofstream ofs(path);  // RAII:构造时打开
    if (!ofs.is_open()) {
        throw std::runtime_error("Cannot open file: " + path);
    }

    ofs << "Hello, World!\n";
    ofs << "Line 2\n";
    // 析构时自动关闭(RAII)
}

// 读文件(逐行)
void ReadFile(const std::string& path) {
    std::ifstream ifs(path);
    if (!ifs) return;  // operator bool() 检查状态

    std::string line;
    while (std::getline(ifs, line)) {
        std::cout << line << "\n";
    }
}

// 读取整个文件到字符串
std::string ReadAll(const std::string& path) {
    std::ifstream ifs(path);
    return std::string(
        std::istreambuf_iterator<char>(ifs),
        std::istreambuf_iterator<char>()
    );
}

⭐ 文件打开模式

模式含义说明
ios::in读取ifstream 默认
ios::out写入(覆盖)ofstream 默认
ios::app追加写入到文件末尾
ios::ate打开后定位到末尾可以修改位置
ios::binary二进制模式不转换换行符
ios::trunc截断(清空)out 配合
cpp
// 追加模式
std::ofstream ofs("log.txt", std::ios::app);

// 二进制读写
std::ofstream bin("data.bin", std::ios::binary);
int data = 42;
bin.write(reinterpret_cast<const char*>(&data), sizeof(data));

std::ifstream bin_in("data.bin", std::ios::binary);
int result;
bin_in.read(reinterpret_cast<char*>(&result), sizeof(result));

⭐ 流状态检查

cpp
std::ifstream ifs("data.txt");
int x;
while (ifs >> x) {           // 读取成功则继续
    std::cout << x << "\n";
}

if (ifs.eof()) {
    std::cout << "Reached end of file\n";
} else if (ifs.fail()) {
    std::cout << "Format error (not an int?)\n";
    ifs.clear();              // 清除错误状态
    ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} else if (ifs.bad()) {
    std::cout << "Critical IO error\n";
}

三、字符串流

stringstream 的典型用法

cpp
#include <sstream>

// 1. 类型转换(数字 ↔ 字符串)
int num = 42;
std::ostringstream oss;
oss << num;
std::string s = oss.str();    // "42"

// 更简洁:std::to_string (C++11)
std::string s2 = std::to_string(42);
int n = std::stoi("42");

// 2. 字符串拼接
std::ostringstream builder;
builder << "Name: " << name << ", Age: " << age;
std::string result = builder.str();

// 3. 字符串分割
std::string input = "hello world foo bar";
std::istringstream iss(input);
std::string word;
std::vector<std::string> words;
while (iss >> word) {
    words.push_back(word);
}

// 4. 按分隔符分割
std::string csv = "a,b,c,d";
std::istringstream ss(csv);
std::string token;
while (std::getline(ss, token, ',')) {
    std::cout << token << "\n";
}

// 5. 格式化输出
std::ostringstream fmt;
fmt << std::fixed << std::setprecision(2) << 3.14159;
std::string pi = fmt.str();  // "3.14"

C++20 std::format

cpp
#include <format>

// C++20 格式化(类似 Python 的 f-string)
std::string s = std::format("Name: {}, Age: {}", "Alice", 30);
std::string hex = std::format("{:#x}", 255);   // "0xff"
std::string pi = std::format("{:.2f}", 3.14159); // "3.14"
std::string pad = std::format("{:>10}", "hello"); // "     hello"

四、C++ 网络编程基础

⭐ TCP/IP 通信模型

TCP 三次握手与四次挥手

⭐ TCP Socket 编程示例

cpp
// === 服务端 ===
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>

void TcpServer(int port) {
    // 1. 创建 socket
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 绑定地址
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    bind(server_fd, (sockaddr*)&addr, sizeof(addr));

    // 3. 监听
    listen(server_fd, 5);

    // 4. 接受连接
    sockaddr_in client_addr{};
    socklen_t client_len = sizeof(client_addr);
    int client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_len);

    // 5. 收发数据
    char buf[1024]{};
    ssize_t n = recv(client_fd, buf, sizeof(buf), 0);
    send(client_fd, "OK", 2, 0);

    // 6. 关闭
    close(client_fd);
    close(server_fd);
}

// === 客户端 ===
void TcpClient(const char* ip, int port) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);

    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    inet_pton(AF_INET, ip, &addr.sin_addr);

    connect(fd, (sockaddr*)&addr, sizeof(addr));
    send(fd, "Hello", 5, 0);

    char buf[1024]{};
    recv(fd, buf, sizeof(buf), 0);
    close(fd);
}

五、IO 多路复用

⭐ select / poll / epoll 对比

特性selectpollepoll
fd 上限1024无限制无限制
fd 传递每次拷贝到内核每次拷贝到内核内核维护,无需拷贝
触发方式水平触发水平触发水平 + 边缘触发
就绪检测遍历全部 O(n)遍历全部 O(n)回调通知 O(1)
适用场景连接数少连接数中等高并发(推荐)

epoll 的基本用法

cpp
#include <sys/epoll.h>

void EpollExample() {
    // 1. 创建 epoll 实例
    int epfd = epoll_create1(0);

    // 2. 注册监听事件
    epoll_event ev{};
    ev.events = EPOLLIN | EPOLLET;  // 读事件 + 边缘触发
    ev.data.fd = server_fd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &ev);

    // 3. 等待事件
    constexpr int MAX_EVENTS = 64;
    epoll_event events[MAX_EVENTS];

    while (true) {
        int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
        for (int i = 0; i < nfds; ++i) {
            if (events[i].data.fd == server_fd) {
                // 新连接到来
                int client = accept(server_fd, nullptr, nullptr);
                // 注册客户端 fd ...
            } else {
                // 数据可读
                HandleClient(events[i].data.fd);
            }
        }
    }
}

六、Reactor 模式

⭐ 单 Reactor 单线程模型

⭐ 主从 Reactor 多线程模型

经典实现:Nginx(多进程 Reactor)、Netty(主从 Reactor)、muduo(one loop per thread)


七、C++17/20 文件系统

std::filesystem(C++17)

cpp
#include <filesystem>
namespace fs = std::filesystem;

// 路径操作
fs::path p = "/home/user/data.txt";
p.filename();       // "data.txt"
p.stem();           // "data"
p.extension();      // ".txt"
p.parent_path();    // "/home/user"

// 文件操作
bool exists = fs::exists(p);
auto size = fs::file_size(p);
fs::copy("src.txt", "dst.txt");
fs::remove("temp.txt");
fs::rename("old.txt", "new.txt");

// 目录遍历
for (const auto& entry : fs::directory_iterator("/home/user")) {
    std::cout << entry.path() << "\n";
}

// 递归遍历
for (const auto& entry : fs::recursive_directory_iterator("/project")) {
    if (entry.path().extension() == ".cpp") {
        std::cout << entry.path() << "\n";
    }
}

// 创建目录
fs::create_directories("/path/to/dir");

八、总结知识图谱

💬 评论

加载评论中...
📑 文章目录