c++文件操作

文件输入输出

头文件是fstream,里面三个可使用类型:
ifstream 从一个文件读取数据,i指inpuit
ofstream 从一个文件写输入,o指output
ftream   给一个文件既读又写
看一个小图

c++文件操作
这就是依赖关系,所以ftream实现了读和写的功能

打开文件

再说打开文件之前先说一下,文件模式,也就是以什么方式打开文件

文件模式

in   以读的方式打开,文件指针在首,文件不存在打开失败
out  以写的方式打开,当文件不存在,新建一个空文件;当文件存在,清除原有内容
app  每次写操作前均定位到文件末尾,一般配合写文件使用,std::ios::out|std::ios::app,没有文件新建文件,这样文件存在的时候不会清空文件,文件指针到达末尾
ate  打开文件后立即定位到文件末尾,一般配合读文件使用,ios::ate|ios::in,没有文件打开失败,有文件文件指针定位到末尾
trunc 截断文件,删除文件内容打开
binary 以二进制的方式进行IO

模式之间是可以 | 或的,因为本身他们就是数值

ifstream 默认是 std::ios::in,不能使用std::ios::out
ofstream 默认是 std::ios::out | std::ios::trunc 
fstream  默认是 std::ios::in | std::ios::out,不能使用std::ios::in

打开文件代码

打开文件的方式很多这里列举常用的:  
ifstream a("E:\aa1.txt", std::ios::in); //第二个参数如果不写,默认是std::ios::in
if(!a.is_open()) {
    std::cout << "a.is_open()" << std::endl;
}
//使用is_open()判断函数是否打开

常见模式组合

说一下常见的模式组合:
对于fstream的std::ios::in | std::ios::out 打开文件,文件指针在首,不会清空文件,文件不存在打开失败
对于std::ios::out | std::ios::trunc 文件不存在新建一个空白文件,文件存在清空文件
对于std::ios::out | std::ios::app   文件不存在新建一个文件,文件存在不清空文件,让文件指针到尾部 

打开失败处理办法

如果打开失败:
IO文件操作的错误状态  
我们在操作文件的时候,可能发生各种各样的状态,流崩溃、Io操作失败、输出流达到了文件的末尾等,c++提供了函数和标志位,这里列出常用的
s.good()  //如果流处于有效状态,返回true,可以用这个函数判断所有的可能错误
s.eof()   //如果流处于文件的末尾,返回true,常常用在遍历文件的时候使用
s.fail()  //如果IO操作失败或者流崩溃,这个函数返回true
std::ios_base::goodbit //文件流是好的可以操作的,值为0
std::ifstream::failbit  //流崩溃
std::ifstream::eofbit   //输出流达到了文件的末
std::ifstream:badbit    //Io操作失败

可以使用rdstate函数,会返回当前流的状态位
if(a.rdstate() & std::ifstream::failbit) {
    std::cout << "failbit" << std::endl;
}
//这样就可以判断当前是因为什么问题导致打开失败

读文件

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
    ifstream a("E:\aa.txt", std::ios_base::in);
    if(!a.is_open()) {
        a.clear(); //文件未打开成功,进行标志位清除
        std::cout << "a.is_open()" << std::endl;
        return -1;
    }
    /*****************************************/

    //第一种方法,使用重载的>>操作符读取,优点方便快捷,缺点属于单个类型的读取,不能自己控制
    //读取一行终止
    char value[128] = {0};
    if(!a.good()) {
        std::cout << "a is not good" << std::endl;
    }
    a >> value; //可传入字符指针,会一直读取,还可使用int float等基本类型读取
    printf("%sn", value);  //一个一个读取

    /*****************************************/

    //第二种方法,使用get()函数,读取一个字节,每调用这个函数字符指针下移
    a.seekg(0, std::ios_base::beg); //文件指针定位到首位置
    while(!a.eof() && a.good()) {
        printf("%cn", a.get());  //一个一个读取
    }

    /*****************************************/

    //第三种方法使用getline实现一行一行的读取
    char value_line[128] = {0};
    a.clear(); //清清除eof标志位,稍后讲解
    a.seekg(0, std::ios_base::beg); //文件指针定位到首位置
    while(!a.eof() && a.good()) {
        a.getline(value_line, 128, 'n');
        //第二个参数的字符个数必须大于文件的一行的个数,第三个参数是终止符,就是读到终止符停止,如果不写,默认就是'n'
        //调用函数后,文件指针会自动到 n的下一个
        printf("%sn", value_line);  //一个一个读取
        memset(value_line, 128, 0); //将数组重新赋值为0
    }
    a.close();
}

写文件

#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
    ofstream a("E:\aa.txt", std::ios_base::out | std::ios_base::trunc);
    if(!a.is_open()) {
        a.clear(); //文件未打开成功,进行标志位清除
        std::cout << "a.is_open()" << std::endl;
        return -1;
    }
    //使用a.good()判断,流的状态是否正常
    //第一种方法,使用重载的<<
    if(!a.good()) {
        std::cout << "a is not good()()" << std::endl;
    }
    a<<"sasaSA";  //优点可以写任意格式,库函数重载了很多版本
    if(!a.good()) {
        std::cout << "a is not good()()" << std::endl;
    }
    a<<1;
    if(!a.good()) {
        std::cout << "a is not good()()" << std::endl;
    }
    a<<1.3;

    /***************************************/
    //第二种方法,使用put函数,一个字节一个字节插入
    //注意的是put插入的是char类型,如果你使用int类型插入会被转为int的ASCII插入
    int i = 6;
    char value[6] = "12345";
    while((i--) && (a.good())) {
        a.put(value[i]);
        a.put('n');
    }
    /***************************************/
    //第三种方法,使用write函数,第一个参数是传入的字符串首地址,第二个参数是传入的大小
    if(!a.good()) {
        std::cout << "a is not good()()" << std::endl;
    }
    a.write(value, 6);

    a.close();
}

关闭文件

当我们对一个文件操作完毕,需要调用a.close()关闭当前文件流,把文件恢复为可访问的状态,并且某些情况还会刷新缓冲区,让缓冲区文件写入文件中,关于缓冲区

缓冲区文章.文件成功打开一定要close()!!!!

更改文件指针

文件指针:下一次文件操作开始的位置,比如我们打开文件std::ios::in 文件指针指向文件的开始位置,使用get每当我们读取的时候文件指针都会下移
使用seekg(pos),一个参数的就是文件指针要达到的绝对位置,文件最开始就是0,依次往后
使用seekg(off_type off, std::ios_base::seekdir dir),第一个参数是文件指针要达到的相对位置,第二个参数实现基准,定义了三个值可以使用
std::ios_base::beg //文件流的开始
std::ios_base::end //文件流的结尾
std::ios_base::cur //文件流当前的位置

注意偏移的位置都是根据基准位置往后移动

显示当前文件指针的位置

a.tellg()  //a代表定义的字符串流

关于clear()和setstate()的问题

clear()  //清楚当前文件流的标志位,在当前文件流产生错误标志位使用
setstate() //函数参数设置为某个状态

对于clear(std::ios_base::end) //把原先的标志位清除,然后赋值新的标志位
默认clear()   //是清楚所有标志位,变为std::ios_base::goodbit
setstate(std::ios_base::end) //不清楚当前标志位,将std::ios_base::end对应的位置位

网上有打开文件失败关于close和clear的先后顺序问题,我这边测试未发现问题,如果大家有问题,欢迎探讨

原文链接: https://www.cnblogs.com/chaohacker/p/12871740.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    c++文件操作

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/347974

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午4:48
下一篇 2023年3月2日 上午4:48

相关推荐