• cpp文件操作


    文件操作

    数据流

    在cpp中,流(stream)是一个抽象概念,用于描述如何从一个位置到又一个位置传输数据。流主要用于I/O操作。

    数据流包括两大类:1. 输入流(istream):数据从某个源流入程序, 2. 输出流(ostream):数据从程序流向某个目的地。

    根据操作对象不同分为文件流、字符串流、控制台流。

    控制台流

    控制台流()主要用于标准输入输出操作的一部分。这些流提供了一个接口,用于与用于进行交互,即从键盘读取和向屏幕输出,无论程序在那种操作系统或平台上运行。

    iostream:同时包括istreamosteam,是一种多继承的关系,在程序应用中可以只包含头文件

    常见对象有:cin(标准输入),cout(标准输出),cerr(用于显示错误信息)。

    <<>>运算符,是ostream类使用友元函数的方式对各种基本数据类型重载了<<操作符,使我们能够方便地将数据输出到流中。

    文件流

    文件流主要包括输入文件流输出文件流输入输出文件流,这些类都定义在头文件中。

    与标准输入输出流cincout不同,文件流需要指定具体的文件来操作。因此,我们需要创建一个流对象并为其指定一个文件名和其他相关属性。

    ofstream类的默认构造函数原形为:

    ofstream::ofstream(const char *filename, int mode = ios::out, int pmode = filebuf::openprot);
    
    • 1

    其中filmname表示指定要打开的文件名。

    mode是一个标志位,用于指定如何打开文件。默认值是ios::out,意味着文件以输出模式打开

    pmode是一个与平台相关的权限参数,指定了文件的权限。

    类型解释
    ios::app输出追加模式。当写入文件时,数据会被追加到文件的末尾,而不是覆盖文件的内容。
    ios::ate初始位置在文件的末尾,但你可以移动到文件中的任何位置进行读写操作。
    ios::binary文件以二进制模式打开。不使用这个模式时,默认为文本模式。
    ios::in文件以输入模式打开(通常与 ifstream 一起使用)。
    ios::out文件以输出模式打开(默认值)。
    ios::trunc如果文件已存在,其内容将被截断或删除。
    ios:nocreate不建立文件,所以文件不存在时打开失败
    ios:.noreplace不覆盖文件,打开文件时如果文件存在失败

    打开文件属性值

    类型解释
    0普通文件,打开访问
    1只读文件
    2隐含文件
    4系统文件

    “或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。  文件使用完后可以使用close成员函数关闭文件。

    ios::app,当你用这种模式打开文件时,先检查文件的状态。例如,你可以使用 file.is_open() 来确定文件是否成功打开,以及使用 file.fail() 来检查是否有任何I/O错误。这有助于确保文件操作的安全和有效。

    字符串流

    字符串流定义在头文件中,主要有以下三种类型的字符串流:

    1. istringstream: 输入字符串流,允许从一个 std::string 对象中读取。
    2. ostringstream: 输出字符串流,允许写入到一个 std::string 对象。
    3. stringstream: 同时支持读写操作的字符串流。

    文件处理

    C++的文件处理也可以看作为一个对象,使用文件流的类,使用头文件,处理的时候有文本文件二进制文件之分,主要的区别就是存储的形式。

    文件处理可以概括成如下几个过程:

    1. 包含头文件
    2. 创建文件流对象
    3. 打开文件
    4. 文件读写
    5. 关闭文件
    打开文件

    打开文件的核心:打开文件涉及到通知操作系统你希望访问文件的特定部分(例如读、写或两者兼而有之),并且通常会得到一个文件句柄或文件描述符,该描述符后续可用于读写操作。

    下面是open()函数的标准语法,open()ifstreamofstreamfstream类的成员函数,用于打开文件。

    void open(const char *filename, ios::openmode mode = ios::in | ios::out);
    
    • 1

    open() 成员函数的第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。

    image-20231010153854667

    以上的不同模式标志,可以组合使用为文件指定复杂的打开行为。

    例如:

    • 写入模式与截断模式
    ofstream outf;
    outf.open("file.txt", ios::out | ios::trunc);
    
    • 1
    • 2

    ios::trunc:当与ios::out一起使用时,这个标志表示如果文件已经存在,则其内容应被截断或清空。如果不指定这个标志并且文件已存在,写入操作通常会覆盖文件的现有内容,从文件的开头开始。

    • 读写模式
    fstream file;
    file.open("file.txt", ios::out | ios::in);
    
    • 1
    • 2

    结合ios::inios::out,意味着你可以对文件进行读写操作。当使用这种模式打开文件时,现有的文件内容不会被自动截断或清空。你可以在文件中任意地移动,进行读和写操作。

    文件的写入与输出
    1. 写入文件

    在cpp中,可以使用流插入运算符(<<)将数据写入文件,类似于将信息输出到控制台的方式。

    对比控制台输出和文件输出:

    std::cout << "Hello, World!";
    
    • 1

    这是cout代表标准输出的ostream类实例。

    std::ofstream outFile("filename.txt");
    outFile << "Hello, File!";
    
    • 1
    • 2

    outFileofstream 类的实例。 ofstream 代表“输出文件流”,允许将数据写入文件。

    1. 读取文件

    从文件读取涉及流提取运算符 ( >> ),类似于从键盘获取输入。唯一不同的是,在这里使用的是 ifstream 或 fstream 对象,而不是 cin 对象。

    1. 关闭文件

    在cpp程序终止时,他会自动关闭并且刷新所有流,释放所有分配的内存,并关闭所有打开的文件,但显示关闭文件是一个好习惯。

    使用完文件后关闭文件的原因如下

    • To make sure that all buffered data gets written.确保所有缓冲数据都被写入。
    • To release the resources associated with the file.释放与该文件关联的资源。
    • To prevent any potential data corruption.防止任何潜在的数据损坏。

    下面是close()函数的标准语法,close() 函数是 fstream、ifstream 和ofstream 对象的一个成员。

    void close()

    文件写入简单示例:

    #include
    #include
    using namespace std;
    
    int main(){
        // 创建流对象
        ofstream outf;
        // 打开文件
        outf.open("file.txt", ios:: app);
        // 写入数据
        outf << "Hello World" << endl;
        // 关闭文件
        outf.close();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    文件读取的简单示例:

    #include
    #include //文件流的头文件
    using namespace std;
    int main()
    {
        char a;
        ifstream infile; //定义ifstream类(输入文件流类)对象outfile
        infile.open("file.txt");//打开文件 使文件流与c++.txt文件建立关联
        while (!infile.eof())
        {
            infile.get(a); //依次获取文件中每个字符 并输出
            cout << a;
        }
        infile.close(); //关闭文件 使文件流与c++.txt文件断开关联
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这种方法效率低,不建议使用。

    第二种方法:

    char buf[1024] = {0};
    while (ifs >> buf) {
        cout << buf << endl;
    }
    
    • 1
    • 2
    • 3
    • 4

    第三种:

    char buf[1024] = {0};
    while (ifs.getline(buf, sizeof(buf))) {
        cout << buf << endl;
    }
    
    • 1
    • 2
    • 3
    • 4

    第四种:

    string buf;
    while (getline(ifs, buf)) {
        cout << buf << endl;
    }
    ifs.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    二进制文件读写

    二进制写文件主要利用流对象调用成员函数write(),这个函数直接从内存中的某个位置(由buffer指针指定)写入指定的字节数(len)到文件中。

    函数原型:ostream& write(const char*buffer,int len);

    #include
    #include //文件流的头文件
    using namespace std;
    class Student {
    public:
        Student() {}
        Student(string name,int age) :name(name), age(age) {}
    protected:
        string name;
        int age;
    };
    int main() {
        ofstream bof;
        Student s1("张三", 100);
        bof.open("student.txt", ios::out|ios::binary);
        bof.write((const char*) & s1, sizeof(Student));
        bof.close();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    读取文件用read 函数从文件中读取指定的字节数并将其放入指定的内存位置。

    ifstream bif;
        bif.open("student.txt", ios::in | ios::binary);
        if (!bif.is_open()) {
            cout << "文件打开失败" << endl;
            return 0;
        }
        Student s2;
        bif.read((char*)&s2, sizeof(Student));
        cout << s2.name << " " << s2.age << endl;
        bif.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    fstream文件操作

    打开文件和关闭文件

    打开文件fstream可以在生命流对象时传入文件名打开文件,也可以使用open()函数打开文件。

    文件打开后必须关闭,fstream提供了close()函数关闭文件。

    打开文件

    使用构造函数声明对象时打开文件:

    fstream ioFile("data.txt", ios::in | ios::out);

    使用open()函数打开文件:

    fstream file;
    file.open("example.txt", ios::in | ios::out);
    
    • 1
    • 2

    如果只传文件名,系统会自动根据文件类型选择默认的打开方式。

    • ios::in:读取模式
    • ios::out:写入模式
    • ios::app:追加模式。数据会被写入文件的末尾而不是覆盖已有内容。
    • ios::trunc:如果文件存在,则先删除文件的内容,然后再打开它。
    • ios::binary:以二进制模式打开文件。

    模式和属性可以单独使用,也可以混合使用。在混合使用时,需要使用逻辑连接符或|链接。

    ios::out会默认清空文件,即ios::out|ios::trunc打开文件的同时清空文件。如果不想清空文件,那么设置读写模式为ios::out|ios::app,以这种模式打开文件后,是以追加内容的方式写入文件。

    fstream提供了多种读写操作,包括:

    • <<>>:这些操作符用于向文件写入数据和从文件读取数据。
    • read()write():这些函数用于处理二进制文件。
    • put()get():这些函数分别用于写入和读取单个字符。
    • getline():这个函数用于从文件中读取一行文本。

    示例:

    读取文本文件:

    ifstream file("example.txt");
    string line;
    while(getline(file, line)) {
        cout << line << endl;
    }
    file.close();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    读取二进制文件:

    ifstream file("binaryExample.bin", ios::binary);
    int number;
    file.read((char*)&number, sizeof(number));
    file.close();
    
    • 1
    • 2
    • 3
    • 4
    • 文本文件:这些文件主要包含文本,如.txt。你通常会使用逐行读取/写入的方式来处理它们。
    • 二进制文件:这些文件包含二进制数据,如图像、音频或编译后的程序。当处理这些文件时,你会使用块读写的方式,这意味着你可能会一次读取/写入多个字节。

    完整示例:

    #include 
    #include   // 1. 包含头文件
    #include 
    using namespace std;
    
    int main() {
        string str;
        fstream iofile;  // 2. 创建对象
    
        // 3. 打开文件并清空内容
        iofile.open("file.txt", ios::out | ios::in | ios::trunc);
    
        // 4. 写入数据
        iofile << "这里是写入内容测试" << endl;
        iofile << "this is test" << endl;
        iofile.close();  // 5. 关闭文件
    
        cout << "写入完毕" << endl;
    
        // 重新打开文件进行读取
        iofile.open("file.txt", ios::out | ios::in);
        while (getline(iofile, str))  // 循环读取
        {
            cout << str << endl;
        }
        iofile.close();
    
        cout << "读取完毕" << endl;
        return 0;
    }
    
    • 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

    二进制数据读写文件:

    #include 
    #include 
    using namespace std;
    
    int main() {
        int numbers[] = {10, 20, 30, 40, 50};
        fstream iofile;
    
        // 1. 打开文件以进行二进制写入
        iofile.open("binaryfile.bin", ios::out | ios::binary | ios::trunc);
        iofile.write((char*) &numbers, sizeof(numbers));
        iofile.close();
    
        cout << "数据已写入二进制文件" << endl;
    
        int readNumbers[5] = {0};
    
        // 2. 打开文件以进行二进制读取
        iofile.open("binaryfile.bin", ios::in | ios::binary);
        iofile.read((char*) &readNumbers, sizeof(readNumbers));
        iofile.close();
    
        cout << "从二进制文件读取的数据:" << endl;
        for(int i = 0; i < 5; i++) {
            cout << readNumbers[i] << " ";
        }
        cout << endl;
    
        return 0;
    }
    
    • 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

    文件定义与大小

    当你在处理文件时,经常需要控制文件的读写位置或查询其大小。C++提供了一组非常强大的工具来实现这一目的,下面将详细介绍这些功能及其用法。

    文件定位:seekg() 和 seekp()

    seekg()seekp() 分别用于设置输入和输出流的位置。

    • seekg():设置输入流的位置(对应读操作)。
    • seekp():设置输出流的位置(对应写操作)。

    这些函数需要两个参数:

    • offset:这是从给定起点移动的字节量。它可以是正数(向前移动)或负数(向后移动)。
    • origin:这定义了从哪里开始计算偏移。常用的起点有:
      • ios::beg:从文件开始处。
      • ios::cur:从文件的当前位置。
      • ios::end:从文件的末尾。
    示例:
    fstream file("example.txt", ios::in | ios::out);
    
    // 将读指针从文件开始处向后移动2个字节
    file.seekg(2, ios::beg);
    
    // 将写指针从当前位置向后移动2个字节
    file.seekp(2, ios::cur);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    2. 获取文件大小:tellg() 和 tellp()

    这两个函数返回当前的读或写位置,通常表示为从文件开始到当前位置的字节数。

    • tellg():获取输入流的当前位置。
    • tellp():获取输出流的当前位置。

    如果你想知道整个文件的大小,一个常见的方法是将读指针移动到文件的末尾,然后使用 tellg()

    示例:
    fstream file("example.txt", ios::in | ios::out);
    
    // 将读指针移动到文件末尾
    file.seekg(0, ios::end);
    
    // 获取当前位置,即文件大小
    streampos size = file.tellg();
    cout << "文件大小是: " << size << " 字节" << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    注意:
    • 在操作完成后,可能需要将文件指针重新定位到适当的位置,以便进行后续的读/写操作。
    • 尝试读取超出文件大小的位置可能会导致未定义的行为,通常是读取失败。
  • 相关阅读:
    【arduino】时间相关函数
    107.(leaflet篇)leaflet态势标绘-钳击箭头采集
    【LeetCode】LeetCode 106.从中序与后序遍历序列构造二叉树
    SpringBoot监控@EnableAdminServer
    IPD的商业实现过程
    1775. 通过最少操作次数使数组的和相等
    android studio的Android Drawable Preview
    华为星闪联盟:引领无线通信技术创新的先锋
    Java集合进阶
    MySQL 教程 1.1
  • 原文地址:https://blog.csdn.net/m0_73790534/article/details/133779705