C++文件IO

本文详细介绍了C++中的文件I/O流,包括ofstream、ifstream和fstream的使用,文件读写步骤,如何进行随机读写,二进制文件操作以及利用typeid获取类型信息。通过实例展示了如何实现学生类对象的读写,并给出了C++版mv命令的设计思路,作为实际应用的练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、I/O流

​ C++把对文件的读写操作都封装在了以下类中:

​ ofstream 对文件的写操作,继承了ostream类的功能

​ ifstream 对文件的读操作,继承了istream类的功能

​ fstream 对文件的读写操作,继承了ofstream、ifstream类的功能

二、C++对文件进行读写的步骤:

1、创建流对象,打开文件
#include <fstream>
void open( const char *filename);
void open( const char *filename, openmode mode);
功能:用于打开文件,且类的构造函数与它们参数一样。
    filename:文件的路径
    mode:打开方式
        ios::app 添加输出 
        ios::ate 当已打开时寻找到EOF 
        ios::binary 以二进制模式打开文件 
        ios::in 为读取打开文件 
        ios::out 为写入打开文件 
        ios::trunc 覆盖存在的文件   
        ifstream 类的默认mode
            只读打开文件,文件不存在则打开失败 r
        ofstream 类的默认mode
            只写打开文件,文件不存在则创建,文件存在则清空。 w
        fstream 类的默认mode r+
            以读写打开文件,文件不存在则打开失败
        注意:这些打开模式单独使用和混合使用的功能有相就的删减,不是简单的功能相加,具体功能可使用 strace 追踪它们底层调用open函数对应
2、判断文件是否打开成功

​ bool good();
​ 功能:判断上一次操作是否成功,可用于判断文件是否打开。
​ 返回值:
​ true:打开成功
​ false:打开失败

3、流对象<< 写操作、流对象>> 读操作

​ ofs << str << endl;
​ ifs >> str;

4、关闭文件

​ void close();

练习1:设计一个学生类并创建对象,然后把对象以文本格式写入stu.txt文件中。
练习2:从stu.txt文件中读写学生类并显示。

注意:在读写类对象时,由于绝大多数成员都是private属性,因此不能在类外进行读写,且由于ostream/istream是ifstream/ofstream/fstream的父类,因此实现<</>>运算符函数既可以用于输入输出对象,也可以用于文本格式的读写。

三、随机读写

C++为流提供了两套设置位置指针的成员函数,为了兼容有两个位置指针系统,但由于Linux和windows系统底层只有一个位置指针,所以使用其中套即可。

istream &seekg( off_type offset, ios::seekdir origin );
功能:偏移值+基础位置设置输入流的位置指针    
origin:        
	ios::beg 文件开头
    ios::end 文件末尾
    ios::cur 当前位置    
    
istream &seekg( pos_type position);    
功能:按绝对位置设置输入流的位置指针
    
ostream &seekp( off_type offset, ios::seekdir origin );    
功能:偏移值+基础位置设置输出流的位置指针    

ostream &seekp( pos_type position );    
功能:按绝对位置设置输出流的位置指针

pos_type tellg();    
功能:获取输入流的位置指针

pos_type tellp();
功能:获取输出流的位置指针
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;

class Student
{
	char name[20];
	char sex;
	short age;
public:
	Student(const char* name,char sex,short age):sex(sex),age(age)
	{
		strcpy(this->name,name);
	}
	friend ostream& operator<<(ostream& os,const Student& stu)
	{
		return os << stu.name << " " << stu.sex << " " << stu.age;
	}
	friend istream& operator>>(istream& is,Student& stu)
	{
		return is >> stu.name >> stu.sex >> stu.age;
	}
};

int main(int argc,const char* argv[])
{
	Student stu("hehe",'m',28);
	fstream fs("text.txt");
	if(!fs.good())
		return -1;
	fs << stu << endl;
	Student stu1("",'w',0);
	fs.seekg(0,ios::beg);
	fs >> stu1;
	cout << stu1 << endl;
  
	fs.close();
}

四、C++对二进制文件进行读写

1、打开文件
使用构造函数,open函数打开文件,mode参数增加ios::binary。    

2、读写        
istream &read( char *buffer, streamsize num );        
buffer:存储数据的缓冲区首地址        
num:缓冲区的大小
        
streamsize gcount();        
功能:获取最后一次读到的字节数
        
ostream &write( const char *buffer, streamsize num );        
buffer:待写入数据的内存首地址        
num:数据的字节数        

使用good函数判断是否写入成功。    

3、关闭文件        
void close();    
注意:在写入对象时,对象的成员中不应该有指针(string)类型的成员。

bool eof();    
功能:判断文件是否到达末尾
	while(true)    
	{        
		// 读操作 fs>>obj fs.read
   	 	if(fs.eof())break;
        // 其它操作    
    }
int main(int argc,const char* argv[])
{
	fstream fs("stu.dat",ios::binary|ios::out|ios::in);
	if(!fs.good())
		cout << "打开失败!" << endl;
	fs.seekg(0,ios::end);
	
	Student* stu = new Student("hehe",'m',18);
	Student* stu1 = new Student("",'w',0);
	
	fs.write((char*)stu,sizeof(Student));
	fs.seekg(0,ios::beg);
	fs.read((char*)stu1,sizeof(Student));
	cout << *stu1 << endl;
	cout << fs.gcount() << endl;
	
	char buf[4096] = {};
	fs.seekg(0,ios::beg);
	while(true)
	{
		fs.read((char*)stu1,sizeof(Student));
		cout << *stu1 << endl;
		if(fs.eof()) break;
	}
	fs.close();
}

五、类型信息

​ C++中的typeid可以获取数据的类型,使用时需要加头文件typeinfo。
​ 1、返回值是type_info类型对象
​ 2、type_info的name成员函数可以获取类型名
​ 3、它还实现了==运算符,可以判断两个数据是否是同一种类型。
​ 4、它可以区别父类指针或引用指向的是哪个子类,但前提是父子类之间构造了多态。

作业:实现一个C++版mv命令。

​ stat
​ 移动文件
​ 源文件是普通文件
​ 重命名 目标不能被打开
​ 不重命名 目标能打开
​ 目标是目录
​ 目标是文件,是否覆盖
​ 重命名
​ 源文件和目标文件在同目录下
​ 目录移动

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

int main(int argc,const char* argv[])
{
	if(3 != argc)
	{
		cout << "Use:mv <src> <dest>" << endl;
		return -1;
	}

	ifstream ifs(argv[1]);
	if(!ifs.good())
	{
		cout << "源文件不存在,请检查" << endl;
		return -1;
	}

	if(0==access(argv[2],F_OK))
	{
		cout << "源文件已存在,是否覆盖(y/n)?";
		char cmd;
		cin >> cmd;
		if(cmd != 'y')
		{
			cout << "停止移动!" << endl;
			ifs.close();
			return 0;
		}
	}

	ofstream ofs(argv[2]);
	if(!ofs.good())
	{
		cout << "目标位置无权限,请检查!" << endl;
		return -1;
	}

	char buf[4096];
	do{
		ifs.read(buf,sizeof(buf));
		ofs.write(buf,ifs.gcount());
	}while(!ifs.eof());

	ifs.close();
	ofs.close();

	remove(argv[1]);
}

可以写在简历中的小工具
mv命令
ping命令
rm -rf命令
ls -la命令
cp多线程

 一、ASCII 输出   为了使用下面的方法, 你必须包含头文件(译者注:在标准C++中,已经使用取 代,所有的C++标准头文件都是无后缀的。)。这是 的一个扩展集, 提供有缓 冲的文件输入输出操作. 事实上, 已经被包含了, 所以你不必包含所有这两个 文件, 如果你想显式包含他们,那随便你。我们从文件操作类的设计开始, 我会讲解如何进行ASCII I/O 操作。如果你猜是"fstream," 恭喜你答对了! 但这篇文章介绍的方法,我们分别使用"ifstream"?和 "ofstream" 来作输入输出。   如果你用过标准控制台流"cin"?和 "cout," 那现在的事情对你来说很简单。 我们现在开始讲输出部 分,首先声明一个类对象。 ofstream fout;   这就可以了,不过你要打开一个文件的话, 必须像这样调用ofstream::open()。 fout.open("output.txt");   你也可以把文件名作为构造参数来打开一个文件. ofstream fout("output.txt");   这是我们使用的方法, 因为这样创建和打开一个文件看起来更简单. 顺便说一句, 如果你要打开的文 件不存在,它会为你创建一个, 所以不用担心文件创建的问题. 现在就输出到文件,看起来和"cout"的操 作很像。 对不了解控制台输出"cout"的人, 这里有个例子。 int num = 150; char name[] = "John Doe"; fout << "Here is a number: " << num << " "; fout << "Now here is a string: " << name << " ";   现在保存文件,你必须关闭文件,或者回写文件缓冲. 文件关闭之后就不能再操作了, 所以只有在你 不再操作这个文件的时候才调用它,它会自动保存文件。 回写缓冲区会在保持文件打开的情况下保存文 件, 所以只要有必要就使用它。回写看起来像另一次输出, 然后调用方法关闭。像这样: fout << flush; fout.close();    现在你用文本编辑器打开文件,内容看起来是这样:   Here is a number: 150 Now here is a string: John Doe   很简单吧! 现在继续文件输入, 需要一点技巧, 所以先确认你已经明白了流操作,对 "<>" 比较熟悉了, 因为你接下来还要用到他们。继续…   二、ASCII 输入   输入和"cin" 流很像. 和刚刚讨论的输出流很像, 但你要考虑几件事情。在我们开始复杂的内容之前 , 先看一个文本:   12 GameDev 15.45 L This is really awesome!   为了打开这个文件,你必须创建一个in-stream对象,?像这样。 ifstream fin("input.txt");   现在读入前四行. 你还记得怎么用"<<" 操作符往流里插入变量和符号吧?好,?在 "<>" (提取) 操作符. 使用方法是一样的. 看这个代码片段.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值