操作文本文件

需要包含头文件#include <fstream>​​

写文件(输出流)

步骤(四步)

  • 创建输出流对象

    ​ofstream fp ; //创建输出流对象​​

  • 打开文件,⚠打开模式缺省时如果文件不存在就创建,文件存在则截断内容

    ​fp.open"文件路径",打开模式"文件路径",打开模式; //按照打开模式打开文件​​

文件路径注意事项:

目录文件可以使用相对路径或绝对路径

如果在windows平台下,因为' \ '为转义字符,可以使用以下方法:

  • "D:\\data\\txt\\test.txt " 使用' \\ '替换' \ '

  • "D:/data/txt/test.txt " 使用' / '替换' \ '

  • R"D:\data\txt\test.txtD:\data\txt\test.txt" 使用原始字面量,C++11标准

打开模式

作用

ios::out

缺省值,会截断文件内容(可理解为覆盖原有内容)

ios::trunc

截断文件内容(可理解为覆盖原有内容)

ios::app

不截断文件内容,在文件尾追加内容

❗打开文件可能不成功,需要判断,使用 输出流对象名.is_open​​ 判断,打开失败返回false;打开成功返回true。

打开文件失败原因:

  1. 目录不存在

  2. 磁盘空间已满

  3. 没有权限(Linux平台下常见)

  • 向文件中写入数据

  • 关闭文件

    ​输出流对象名.close; //关闭文件​​

演示代码:

#include <iostream>
#include <fstream> //操作文件

int    main(){
    std::ofstream file1;    //1.创建输出流对象
    //std::string filename = "log.txt";    //string
    char filename[] = "log.txt";            //C风格字符串
    //file1.open(filename);            //2.打开文件,文件不存在就创建,文件存在清空内容,再写入
    //file1.open(filename,std::ios::out);
    //file1.open(filename,std::ios::trunc);
    file1.open(filename,std::ios::app);        //打开文件,文件不存在就创建,文件存在就在文件尾追加内容
    //3.写入内容
    if(file1.is_open() == false){                //输出流对象名.is_open()用于判断文件是否打开
        std::cout << " 文件打开失败 " << std::endl;
    }
    else{
        file1 << "春风得意马蹄疾,一日看尽长安花。\n";
        file1<<"                  ——孟郊《登科后》\n";
        std::cout << " 文件操作成功 " << std::endl;
    }

    //4.关闭文件
    file1.close();

    return 0;
}

读文件(输入流)

步骤(四步)

  • 创建输入流对象

    ​ifstream fp; //创建输入流对象​​

  • 打开文件⚠文件不存在时打开文件失败

    fp.open文件路径,打开模式文件路径,打开模式;//打开模式缺省值为ios::in​​

打开文件失败原因:

  1. 目录不存在

  2. 文件不存在

  3. 没有权限(Linux平台下常见)

  • 从文件中读取数据(三种方法)

文本文件一般以行的方式组织数据

  1. getline函数

​getline输入流对象名,缓冲区输入流对象名,缓冲区;​​ 缓冲区需要提前定义

#include <iostream>
#include <fstream>

int main(){
    std::ifstream fin;    //创建输入流对象
    std::string filename = "log.txt";
    fin.open(filename,std::ios::in);        //打开文件,ios::in 为缺省值
    std::string buffer;                    //缓冲区
    //char buffer[101];                //缓冲区
    if(fin.is_open() == false){
        std::cout << " 文件打开失败 " <<std::endl;
    }
    else{
          while(getline(fin,buffer)){        //使用while读取多行数据
              std::cout << buffer <<std::endl;
              }
        std::cout << " 文件打开成功 " <<std::endl;
        }
    //关闭文件
    fin.close();
    return 0;
}
  1. 输入流getline函数

​输入流对象名.getline缓冲区,最多读取的字节数缓冲区,最多读取的字节数​​

⚠如果采用这种方式读取,一定要保证缓冲区足够大,超过缓冲区的部分读取不成功

#include <iostream>
#include <fstream>

int main(){
    std::ifstream fin;    //创建输入流对象
    std::string filename = "log.txt";
    fin.open(filename,std::ios::in);        //打开文件,ios::in 为缺省值
    std::string buffer;                    //缓冲区
    //char buffer[101];                //缓冲区
    if(fin.is_open() == false){
        std::cout << " 文件打开失败 " <<std::endl;
    }
    else{
          while(fin.getline(buffer,100)){        //使用while读取多行数据
              std::cout << buffer <<std::endl;
              }
        std::cout << " 文件打开成功 " <<std::endl;
        }
    //关闭文件
    fin.close();
    return 0;
}
  1. 使用>>运算符

​输入流对象名 >> 缓冲区​​

⚠>>运算符从文件中读取文本内容时会将空格、制表符、换行符、视为分隔符,读取并返回下一个非空白字符之前的字符,它将跳过所有连续的空白字符,直到遇到一个非空白字符。

例如:

春风得意马蹄疾,一日看尽长安花。 ——孟郊《登科后》

使用>>运算符读取会变成

春风得意马蹄疾,一日看尽长安花。

——孟郊《登科后》

#include <iostream>
#include <fstream>

int main(){
    std::ifstream fin;    //创建输入流对象
    std::string filename = "log.txt";
    fin.open(filename,std::ios::in);        //打开文件,ios::in 为缺省值
    std::string buffer;                    //缓冲区
    //char buffer[101];                //缓冲区
    if(fin.is_open() == false){
        std::cout << " 文件打开失败 " <<std::endl;
    }
    else{
          while(fin >> buffer){        //使用while读取多行数据
              std::cout << buffer <<std::endl;
              }
        std::cout << " 文件打开成功 " <<std::endl;
        }
    //关闭文件
    fin.close();
    return 0;
}
  1. 使用字符串输出流操作符,它将整个文件内容读入字符串流(包括空白字符)

解决>>运算符跳过空白字符的问题

#include <iostream>
#include <fstream>
#include <sstream>    //字符串流的头文件

int main(){
    std::ifstream fin;    //创建输入流对象
    std::string filename = "log.txt";
    fin.open(filename,std::ios::in);    //打开文件,ios::in 为缺省值
    std::string buffer;        //缓冲区
    //char buffer[101];            //缓冲区

    std::ostringstream fstr ; //字符串输出流
    fstr << fin.rdbuf();    // 将整个文件内容读入字符串流
    buffer = fstr.str();          // 从字符串流中获取字符串

    if(fin.is_open() == false){
        std::cout << " 文件打开失败 " <<std::endl;
    }
    else{
        std::cout << buffer << std::endl;
    }
    //关闭文件
    fin.close();
    return 0;
}

操作二进制文件

写入二进制文件(输出流)

步骤(四步)

  • 创建输出流对象

    ​ofstream fp ; //创建输出流对象​​

  • 打开文件,⚠打开模式缺省时如果文件不存在就创建,文件存在则截断内容

    ​fp.open"文件路径",打开模式"文件路径",打开模式; //按照打开模式打开文件​​

文件路径注意事项:

目录文件可以使用相对路径或绝对路径

如果在windows平台下,因为' \ '为转义字符,可以使用以下方法:

  • "D:\\data\\txt\\test.txt " 使用' \\ '替换' \ '

  • "D:/data/txt/test.txt " 使用' / '替换' \ '

  • R"D:\data\txt\test.txtD:\data\txt\test.txt" 使用原始字面量,C++11标准

打开模式

作用

ios::out

缺省值,会截断文件内容(可理解为覆盖原有内容)

ios::trunc

截断文件内容(可理解为覆盖原有内容)

ios::app

不截断文件内容,在文件尾追加内容

ios::binary

以二进制方式打开文件

打开模式可以多个组合

例如:

​ios::binary | ios::app ​​表示以二进制方式打开文件并在文件尾追加数据

❗打开文件可能不成功,需要判断,使用 输出流对象名.is_open​​ 判断,打开失败返回false;打开成功返回true。

打开文件失败原因:

  1. 目录不存在

  2. 磁盘空间已满

  3. 没有权限(Linux平台下常见)

  • 向文件中写入数据

使用write函数

​输出流对象名.write数据地址,数据大小数据地址,数据大小​​,数据地址为const char*​​类型,必要时需要强制转换

  • 关闭文件

    ​输出流对象名.close; //关闭文件​​

演示代码

将结构体的数据写入log.dat文件中

#include <iostream>
#include <fstream> //操作文件

struct students{
    char name[31];
    int age;
    int height;
    double weight;
}stu;

int    main(){
    std::ofstream file1;    //1.创建输出流对象
    //std::string filename = "log.dat";    
    char filename[] = "log.dat";    //C风格字符串
    //file1.open(filename);    //2.打开文件,文件不存在就创建,文件存在清空内容,再写入
    //file1.open(filename,std::ios::out);
    //file1.open(filename,std::ios::trunc);
    //file1.open(filename,std::binary);        //二进制打开文件
    file1.open(filename,std::ios::app | std::ios::binary);        //打开二进制文件,文件不存在就创建,文件存在就在文件尾追加内容
    //3.写入内容
    if(file1.is_open() == false){                //输出流对象名.is_open()用于判断文件是否打开
        std::cout << " 文件打开失败 " << std::endl;
    }
    else{
        stu = {"张三",19,175,60.10};
        file1.write((const char*)&stu,sizeof(students));    //强制转换为const char*
        students stu2;
        stu2 = {"李四",20,180,81.60};
        file1.write((const char*)&stu2,sizeof(students));
        std::cout << " 文件操作成功 " << std::endl;
    }

    //4.关闭文件
    file1.close();

    return 0;
}

读取二进制文件(输入流)

读取二进制文件的前提是知道数据格式,例如上面的写入,想要读取就要知道结构体的数据格式

步骤(四步)

  • 创建输入流对象

    ​ifstream fp; //创建输出流对象​​

  • 打开文件⚠文件不存在时打开文件失败

    fp.open文件路径,打开模式文件路径,打开模式;//打开模式缺省值为ios::in​​

打开文件失败原因:

  1. 目录不存在

  2. 文件不存在

  3. 没有权限(Linux平台下常见)

  • 从文件中读取数据

使用read函数

​输出流对象名.read数据地址,数据大小数据地址,数据大小​​,数据地址为const char*​​类型,必要时需要强制转换

  • 关闭文件

​输出流对象名.close; //关闭文件​​

演示代码

#include <iostream>
#include <fstream>

//二进制写入的数据格式,读时必须要知道数据格式
struct students {
    char name[31];
    int age;
    int height;
    double weight;
} stu;

int main() {
    std::ifstream file1;     //创建输入流对象
    //char filename[] = "log.dat";
    std::string filename = "log.dat";
    file1.open(filename, std::ios::binary);    //以二进制的方式打开文件


    if (file1.is_open() == false) {
        std::cout << " 文件打开失败 " << std::endl;
    } else {
        while (file1.read((char*)&stu, sizeof(stu))) {
            std::cout << stu.name << " " << stu.age << " " <<
                      stu.height << " " << stu.weight << std::endl;
        }

    }

    //关闭文件
    file1.close();
    return 0;
}

操作文本文件和二进制文件的细节🔍

  • 在Windows平台下,文本文件的换行标志是'\r\n',Linux平台下,文本文件的换行标志是'\n'

  • 在Windows平台下,以文本文件方式打开文件,写入时,系统会将'\r\n',转换为'\n';读取时系统会将'\n'转换为'\r\n'

    在Linux平台下,系统不会做任何转换

  • 以文本文件打开并读取文件时,遇到换行符停止,读取的内容没有换行符

    以二进制文件打开并读取文件时,遇到换行符并不会停止,换行符会被视为数据

实际开发使用注意

  • 以文本模式打开文本文件,用行的方式操作它

  • 以二进制模式打开二进制文件,用数据块的方法操作它

  • 不关心数据的内容(例如复制/传输)时以二进制模式打开二进制文件,用数据块的方法操作它