C++ fstream标准输入/出流

C++ fstream标准输入/出流

一、fstream标准输入/输出流

核心功能与特性

  1. 文件读取:支持从文本文件或二进制文件中读取数据,可按字符、行、格式化数据(如整数、浮点数)等方式读取。
  2. 自动资源管理:对象析构时会自动关闭关联的文件,避免手动管理文件句柄的繁琐和遗漏。
  3. 模式支持:默认以文本模式打开文件,也可显式指定为二进制模式(std::ios::binary),用于读取二进制数据(如图片、自定义格式文件)。

二、ifstream 标准输入流

ifstream(输入文件流)常用函数及用法

函数 / 操作 说明 示例代码
open() 打开文件,支持指定路径和打开模式(如ios::in(输入模式)、ios::binary(二进制模式)等) `ifstream file; file.open("data.txt", ios::in ios::binary);`
is_open() 检查文件是否成功打开,返回bool if (!file.is_open()) { cerr << "文件打开失败" << endl; }
close() 关闭文件,释放资源(对象析构时自动关闭,手动关闭更严谨) file.close();
getline() 读取一行文本到std::string对象 string line; while (getline(file, line)) { cout << line << endl; }
>> 运算符 格式化读取(如整数、浮点数、字符串等结构化数据) int num; double val; file >> num >> val;
read() 二进制读取,将指定字节数的数据读入字符数组 char buf[100]; file.read(buf, 50); // 读取50字节到buf
eof() 检查是否到达文件末尾,返回bool while (!file.eof()) { /* 执行读取操作 */ }
fail() 检查是否发生读取错误(如格式不匹配、读取越界等) if (file.fail()) { cerr << "读取失败" << endl; }
seekg() 设置读取指针位置(支持ios::beg(文件开头)、ios::cur(当前位置)、ios::end(文件末尾)偏移) file.seekg(20, ios::beg); // 从文件开头偏移20字节
tellg() 获取当前读取指针的位置(返回字节数) streampos pos = file.tellg(); cout << "当前读取位置:" << pos << endl;
#include <iostream>
#include <fstream>  // 包含ifstream
#include <string>

int main() {
    // 1. 创建ifstream对象,打开文件(若文件不存在,is_open()会返回false)
    std::ifstream inFile("input.txt");  // 文件名可替换为实际路径(如"../data.txt")

    // 2. 检查文件是否成功打开
    if (!inFile.is_open()) {
        std::cerr << "错误:无法打开文件 input.txt!" << std::endl;
        return 1;  // 打开失败,退出程序
    }

    // 3. 逐行读取文件内容(使用getline)
    std::string line;  // 存储每行内容
    std::cout << "文件内容如下:" << std::endl;
    while (std::getline(inFile, line)) {  // 读取一行到line,直到文件末尾
        std::cout << line << std::endl;   // 输出当前行
    }

    // 4. 检查读取过程中是否发生错误(非文件末尾的错误)
    if (inFile.fail() && !inFile.eof()) {
        std::cerr << "错误:读取文件时发生异常!" << std::endl;
    }

    // 5. 关闭文件(对象析构时会自动关闭,手动关闭更规范)
    inFile.close();

    return 0;
}

三、标准输出流

ofstream(输出文件流)常用函数及用法

函数 / 操作 说明 示例代码
open() 打开文件,支持模式有ios::out(默认,覆盖文件)、ios::app(追加模式)、ios::binary(二进制模式)等 `ofstream file; file.open("log.txt", ios::out ios::app);`
is_open() 检查文件是否成功打开,返回bool if (!file.is_open()) { cerr << "文件打开失败" << endl; }
close() 关闭文件,释放资源 file.close();
<< 运算符 格式化写入(如字符串、整数、浮点数等结构化数据) file << "ID: " << 1001 << ", Score: " << 95.5;
write() 二进制写入,将字符数组的指定字节数写入文件 char buf[] = "binary data"; file.write(buf, sizeof(buf));
seekp() 设置写入指针位置 file.seekp(10, ios::beg); // 从文件开头偏移10字节开始写入
tellp() 获取当前写入指针的位置(返回字节数) streampos pos = file.tellp(); cout << "当前写入位置:" << pos << endl;
flush() 强制刷新输出缓冲区,立即将数据写入文件(避免缓冲区未满时数据丢失) file.flush();
#include <iostream>
#include <fstream>  // 包含ofstream
#include <string>

int main() {
    // 1. 创建ofstream对象,打开文件(默认模式为ios::out,会覆盖原有内容;若要追加,用ios::app)
    std::ofstream outFile("output.txt");  // 文件名可替换为实际路径

    // 2. 检查文件是否成功打开
    if (!outFile.is_open()) {
        std::cerr << "错误:无法创建/打开文件 output.txt!" << std::endl;
        return 1;
    }

    // 3. 向文件写入内容(使用<<运算符,类似cout)
    outFile << "这是第一行文本" << std::endl;  // 写入字符串并换行
    outFile << "第二行:包含一个数字 " << 123 << std::endl;  // 混合写入字符串和整数
    outFile << "第三行:浮点数 " << 3.14159 << std::endl;    // 写入浮点数

    // 4. 强制刷新缓冲区(立即将数据写入文件,避免程序崩溃时数据丢失)
    outFile.flush();

    // 5. 关闭文件
    outFile.close();

    std::cout << "内容已成功写入 output.txt!" << std::endl;
    return 0;
}

四、实战案例

struct Point {
 int id;
 double x;
 double y;
 double z;

 // ==重载
 bool operator==(const Point &p)  
 {
     if(this->x == p.x && this->y == p.y && this->z == p.z)
     {
         return true;
     }
     return false;
 }
};

std::vector<Point> readPointsFromCSV(const std::string& filename) {
 std::vector<Point> points;
 std::ifstream file(filename);
 if (file.is_open()) {
     std::string line;
     // 跳过标题行
     std::getline(file, line);
     std::getline(file, line);
     while (std::getline(file, line)) {
         // 遇到空行则终止循环
         if (line.empty()) {
             break;
         }
         std::stringstream ss(line);
         std::string id_str, x_str, y_str, z_str;
         std::getline(ss, id_str, ',');
         std::getline(ss, x_str, ',');
         std::getline(ss, y_str, ',');
         std::getline(ss, z_str, ',');

         Point p;
         p.id = std::stoi(id_str);
         p.x = std::stod(x_str);
         p.y = std::stod(y_str);
         p.z = std::stod(z_str);
         points.push_back(p);
     }
     file.close();
 }
 return points;
}

std::vector<Segment> readSegmentsFromCSV(const std::string& filename) {
    //变关系顺序表
    std::vector<Segment> segments;
    //标准输入流  打开文件
    std::ifstream file(filename);
    bool isPointsSection = true;
    if (file.is_open()) {
        std::string line;
        while (std::getline(file, line)) {
            if (line.find("# Segments section") != std::string::npos) {
                isPointsSection = false;
                // 跳过标题行
                std::getline(file, line);
                continue;
            }
            if (!isPointsSection) {
                std::stringstream ss(line);
                std::string id_str, startId_str, endId_str;
                std::getline(ss, id_str, ',');
                std::getline(ss, startId_str, ',');
                std::getline(ss, endId_str, ',');

                Segment s;
                s.id = std::stoi(id_str);
                s.startPointId = std::stoi(startId_str);
                s.endPointId = std::stoi(endId_str);
                segments.push_back(s);
            }
        }
        file.close();
    }
    return segments;
}

这段代码的核心功能是将一个字符串按逗号分隔成多个子串,通常用于解析 CSV 格式的单行数据(如从文件中读取的一行点坐标数据)。以下是逐行解释:

1. std::stringstream ss(line);

  • std::stringstream 是 C++ 标准库中的字符串流类(需包含 <sstream> 头文件),可以像操作输入流(如 cin)一样操作字符串。
  • 这行代码创建了一个 stringstream 对象 ss,并将字符串 line 的内容传入 ss 中。此后,ss 就可以像 “内存中的输入流” 一样,从中读取数据。

2. std::string id_str, x_str, y_str, z_str;

  • 定义了 4 个字符串变量,用于存储从 line 中分割出的子串(通常对应 CSV 中的列值,如点的 ID、X 坐标、Y 坐标、Z 坐标)。

3. std::getline(ss, 变量名, ',');

  • std::getline 是用于从流中读取字符串的函数,这里的用法是按指定分隔符(逗号 ,)分割字符串流 ss 中的内容

  • 函数参数说明:getline(输入流, 接收结果的字符串, 分隔符),作用是从输入流中读取字符,直到遇到分隔符(或流结束),将读取到的内容存入接收字符串中(分隔符本身不会被存入)。

    • 第一次:std::getline(ss, id_str, ',')

      ss 中读取字符,直到遇到第一个逗号 ,,将内容存入 id_str(例如,若 line"0,-0.098,4.79,0.0",则 id_str 会是 "0")。

    • 第二次:std::getline(ss, x_str, ',')

      从第一个逗号后的位置继续读取,直到遇到第二个逗号,内容存入 x_str(上例中会得到 "-0.098")。

    • 第三次:std::getline(ss, y_str, ',')

      继续读取,直到第三个逗号,内容存入 y_str(上例中会得到 "4.79")。

    • 第四次:std::getline(ss, z_str, ',')

      继续读取,直到第四个逗号(或流结束),内容存入 z_str(上例中会得到 "0.0")。

整体作用

假设 line 是 CSV 文件中的一行点数据(如 "3,0.479,-4.873,0.000"),这段代码会将其按逗号分割,最终:

  • id_str = "3"(点 ID 的字符串形式)
  • x_str = "0.479"(X 坐标的字符串形式)
  • y_str = "-4.873"(Y 坐标的字符串形式)
  • z_str = "0.000"(Z 坐标的字符串形式)

后续通常会通过 std::stoi(转整数)、std::stod(转浮点数)将这些字符串转换为对应的数据类型,存入结构体(如 Point)中。

注意点

  • line 中的逗号数量少于 3 个(如只有 2 个逗号),则后面的变量会接收剩余所有内容(例如 z_str 可能为空或包含多余字符),需注意后续转换时的错误处理。
  • line 中没有逗号,id_str 会接收整个 line,其余变量为空。
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务