C++是如何进行文件操作的,让博主教你怎么使用io流来进行文件操作

io流


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1mPkSofr-1665306458976)(D:\gitee仓库\博客使用的表情包\请坐.png)]

1.C++与C语言的字符串有什么区别🐣

​ 有些同学可能会说C语言和C++的字符串不都是一样的吗,不都是字符数组里面放着很多字符嘛,这有啥不一样的。

那么大家可以使用一下下面的代码用例来试试。

#include<iostream>
#include<string>
using namespace std;

struct student
{
	string name = "peter";
	int age = 18;
};

int main()
{
	student s1;
	cin >> s1.name >> s1.age;
	cout << "名字:" << s1.name << " 年龄:" << s1.age << endl;

	scanf("%s%d", s1.name.c_str(), &s1.age);
	cout << "名字:" << s1.name << " 年龄:" << s1.age << endl;
	printf("名字:%s 年龄:%d\n", s1.name.c_str(), s1.age);
	return 0;
}

​ 为什么会出现这样的结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDvHTLfN-1665306458977)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009153141231.png)]

为什么会出现这样的结果呢?使用scanf输入了,李思思,18

结果cout输出的是不完整的李思

printf输出的是完整信息。


​ C语言字符串:char str[]–是遇到\0结束的。

​ C++的串,是一格string的类,是类里面的size()为结束标志。如果大家想再深入理解理解string,可以看看这篇string的模拟实现。

(336条消息) C++的string你可能会用,但是你模拟实现过了吗?带你实现以下string的重要接口!_龟龟不断向前的博客-CSDN博客

当我们使用cin输入字符串时,由于cin是在string类中operator >>过了,使用cin输入,会自动改变_size的位置,当然也会进行增容。

而使用scanf输入string的串,不会改变_size的位置,也不会自动增容。只会决定\0的位置。就像下面的图一样。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nz9BpijH-1665306458978)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009154118299.png)]


​ 所以上述代码,还会出现以下的情况。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VZjCpYIu-1665306458978)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009154323037.png)]

​ 程序卡死了,因为使用scanf不会完成增容,发生越界了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-It9B1iXI-1665306458979)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009154439399.png)]


​ 温馨提示:在C++中,建议去使用cout,cin,如果有一些输出情况实在是使用cout不爽,也可以使用printf,输出字符串的时候一定要小心,谨慎。

2.如何解决OJ题目中的输入多组测试用例🐬

#include<iostream>
#include<string>
using namespace std;

int main()
{
	//c形式
	char str[] = "";
	while ((scanf("%s", str)) != EOF)
	{
		printf("%s\n", str);
	}

	return 0;
}

​ 测试用例输入完了,scanf就会输入失败,返回EOF(-1)。


#include<iostream>
#include<string>
using namespace std;

int main()
{
	//c++形式
	string s;
	while (cin >> s)
	{
		cout << s << endl;
	}

	return 0;
}

​ 这里会不太好理解,C++为了可以实现输入多组测试用例的功能,对istream的类进行了一些操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZhz4avk-1665306458979)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009155154065.png)]

​ 这样子使得这个自定义类型的对象可以**直接用作条件逻辑判断。**就类似于进行了类型转换,将自定义类型转换成了bool类型,

输入成功返回true,输入失败或者遇到流结束标志返回false。

上述代码我们可以通过输入ctrl+C(流结束标志)来结束循环


3.C++是怎么进行文件的读写的?🦝

​ C++的读写主要靠的是这两个类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQlBLbIB-1665306458980)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009160109598.png)]

​ 这里大部分同学会弄混,这里我们细说以下读和写的概念。

–读进来,将文件里面的内容读入内存当中去(in),–写出去,将内存中的内容写到文件里面去。(out)

所以ifstream负责文件的读,ofstream负责文件的写。


文件的读写功能🚀

​ 代码演示:

#include<iostream>
#include<string>
#include<iostream>
#include<fstream>
using namespace std;

void ReadFile()
{
	ifstream ifs("test.cpp");//建立ifs与test.cpp文件的联系
	char ch;
	while (ifs)
	{
		cout << (char)ifs.get();//一个字节一个字节的取出test.cpp的内容,读进ch里面
	}//由于get()的返回类型是int类型,将ch的内容已字符的形式输出
}

void WriteFile()
{
	ofstream ofs("write.txt");//建立ifs与write.txt的联系
	ofs.put('x');//将字符x写进write.txt中
	ofs.write("hello world", 10);//将hello world写进write.txt中
}


void ReadFile()
{
	ifstream ifs("test.cpp");//建立ifs与test.cpp的联系
	while (ifs)
	{
		char ch = (char)ifs.get();//将test.cpp的内容按字节读进ch中
		cout << ch;
	}
}

void WriteFile()
{
	ofstream ofs("filename.txt");//写--新建一个文件,将内容写到文件里面
	//建立ofs与filename.txt的联系
	ofs.put('x');
	ofs.put('\n');
	ofs.write("hello world",11);//要写大小
}

int main()
{
	ReadFile();
	WriteFile();
	return 0;
}

​ 文件读函数的test.cpp的文件是博主写代码的文件。所以会出现下面的输出结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-twCPN5Qe-1665306458981)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009162312746.png)]

​ 不知道为啥,看到自己写的代码被放在这个黑白屏,有点解压的感觉。


文件写函数的效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qSqSOp8C-1665306458981)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009161747680.png)]

打开当先文件目录,会发现生成了一个write.txt的文件,文件内容是

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgCJyuXn-1665306458982)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009161935104.png)]

注意:我们上述代码,写文件,写进文件的内容都是字符串,因为文件只支持写进字符,数字和汉字直接写进去就会使乱码。


设计一个类来完成文件的读写

​ 使用这个类里存放读写的信息。

struct ServeInfo
{
	char _ip[20];//ip地址
	int _port;//端口
};

​ 使用这个类来实现文件的读写功能

class ConfigManager//文件处理类
{

public:
	ConfigManager(const char* filename)//传入文件名
		:_filename(filename)
	{}
    
    //…………文件处理

private:
	string _filename;//文件名
};
二进制方式读写文件👻

​ 关键成员函数ofstream--write(),ifstream--read().

void WriteFileBin(ServeInfo& Winfo)
{
    ofstream ofs(_filename);//建立ofs与文件的联系,用ofs来控制文件
    ofs.write((char*)&Winfo,sizeof(Winfo));//将winfo的内容已二进制的形式写进文件
}

void ReadFileBin(ServeInfo& Rinfo)//要将文件的内容已二进制的方式读进这个类
{
    ifstream ifs(_filename);//先建立ifs与文件的联系
    ifs.read((char*)&Rinfo, sizeof(Rinfo));//二进制读
}

#####二进制读写完整版的代码与效果:

#include<iostream>
#include<string>
#include<iostream>
#include<fstream>
using namespace std;

struct ServeInfo
{
	char _ip[20];//ip地址
	int _port;//端口
};


class ConfigManager//文件处理类
{

public:
	ConfigManager(const char* filename)//传入文件名
		:_filename(filename)
	{}

	void WriteFileBin(ServeInfo& Winfo)//要将这个类用二进制的形式写进文件
	{
		ofstream ofs(_filename);//建立ofs与文件的联系,用ofs来控制文件
		ofs.write((char*)&Winfo,sizeof(Winfo));
	}

	void ReadFileBin(ServeInfo& Rinfo)//要将文件的内容已二进制的方式读进这个类
	{
		ifstream ifs(_filename);//先建立ifs与文件的联系
		ifs.read((char*)&Rinfo, sizeof(Rinfo));//二进制读
	}

private:
	string _filename;//文件名
};

int main()
{
	ServeInfo Winfo = { "192.0.0.1", 80 };//信息
	ServeInfo Rinfo;
	//二进制写出去
	ConfigManager WRcfig("config.txt");
	WRcfig.WriteFileBin(Winfo);//将Winfo写出去
	WRcfig.ReadFileBin(Rinfo);//将文件内容读进Rinfo
	return 0;
}

写出去的效果

当前目录下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4cZMn4gs-1665306458983)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009163756776.png)]

​ 那192.0.0.1是正常的,但是后面的部分怎么不一样了呢,P是啥。因为文件接收字符串的内容,才能显示原本的内容,不然就是一些乱码

解决方法:

  1. 方法一:先转换成字符串,再写进文件里面
  2. 方法二:使用文本输入(就像C语言里面有文本输入是一样的fscanf,fprintf一样的–只是设计者干了更多的事情)。

读进来的效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1yp9ilJn-1665306458983)(C:\Users\Cherish\AppData\Roaming\Typora\typora-user-images\image-20221009164411112.png)]

二进制读写文件的好处:访问高效,代码简洁。

因为文本读写是在二进制的基础上做个一些操作的,效率肯定是高于二进制的。

这也为什么有些同学写的文件版本的通讯录使用的是二进制的读写了。


文本方式读写文件🐻

文本方式呢,说的直白一点,就是想让内容写进文件里面的时候,我们可以看懂里面的内容。

​ 咱们直接放完整版本的。

传统写法:-- 先将内容转换成字符形式,再写进文件
#include<iostream>
#include<string>
#include<iostream>
#include<fstream>
using namespace std;

struct ServeInfo
{
	char _ip[20];
	int _port;
};


class ConfigManager
{

public:
	ConfigManager(const char* filename)
		:_filename(filename)
	{}

	void WriteFileTxt( ServeInfo& Winfo)
	{
		ofstream ofs(_filename);
		ofs.write(Winfo._ip, strlen(Winfo._ip));
        
		ofs.put('\n');
		string s = to_string(Winfo._port);
		ofs.write(s.c_str(), s.size());

	}

	void ReadFileTxt(ServeInfo& Rinfo)
	{
		ifstream ifs(_filename);//建立与文件的联系
		ifs.getline(Rinfo._ip, strlen(Rinfo._ip));//第二个参数是大小
        
		char buff[20];
		ifs.getline(buff, 20);
		Rinfo._port = stoi(buff);
	}


private:
	string _filename;
};

int main()
{
	ServeInfo Winfo = { "192.0.0.1", 80 };
	ServeInfo Rinfo;
	ConfigManager WRcfig("config.log");
	WRcfig.WriteFileTxt(Winfo);//把Winfo写入文件
	WRcfig.ReadFileTxt(Rinfo);
	return 0;
}

使用io流–俺只能说牛逼
#include<iostream>
#include<string>
#include<iostream>
#include<fstream>
using namespace std;

struct ServeInfo
{
	char _ip[20];//ip地址
	int _port;//端口
};


class ConfigManager//文件处理类
{

public:
	ConfigManager(const char* filename)//传入文件名
		:_filename(filename)
	{}


	//现代写法--使得可读性变得很高
	void WriteFileTxt( ServeInfo& Winfo)
	{
		ofstream ofs(_filename);//建立ofs的联系
		ofs << Winfo._ip << Winfo._port;//Winfo的ip与port流入了ofs
	}

	void ReadFileTxt(ServeInfo& Rinfo)
	{
		ifstream ifs(_filename);//建立ifs与文件的联系
		ifs >> Rinfo._ip >> Rinfo._port;
	}


private:
	string _filename;//文件名
};


int main()
{
	ServeInfo Winfo = { "192.0.0.1", 80 };
	ServeInfo Rinfo;
	ConfigManager WRcfig("config.log");
	WRcfig.WriteFileTxt(Winfo);//把Winfo写入文件
	WRcfig.ReadFileTxt(Rinfo);
	return 0;
}

4.C++sstream🤖

#include<iostream>
#include<string>
#include<sstream>
using namespace std;

struct Message
{
	char _name[20];
	int  _id;
	char _time[20];

};

int main()
{
	Message wm = { "张三", 202103008, "2021-9-1" };
	Message rm;
	//如果想将这个对象的内容读进字符串里面
	//或者想将串的内容一次放进对象里面怎么办
	stringstream ssm;
	//将wm的内容已字符串的形式写出去ssm
	ssm << wm._name << " " << wm._id << " " << wm._time;//流是已空格分隔的
	string buff = ssm.str();//再将ssm的内容以字符串的形式读入buff

	ssm >> rm._name >> rm._id >> rm._time;
	return 0;
}

​ 文章主要内容就结束了,这些东西不需要死记,忘记了再回来看看怎么用就行。要常回博主文章看看哦。

不足之处还请各位佬的指点。下期间!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zf6iZkAT-1665306458984)(D:\gitee仓库\博客使用的表情包\给点赞吧.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c326AyWF-1665306458984)(D:\gitee仓库\博客使用的表情包\要赞.jpg)]

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值