您的位置:首页 > 编程语言 > C语言/C++

c++文件的输入输出

2018-03-10 15:06 609 查看
c++文件的输入输出用到ifstream、ofstream、fstream这三个类。接下来我们详细介绍这三个类及其方法。

#include<fstream>   //使用c++文件流要包含的头文件
ifstream    //文件的读操作,将文件读入到内存中
ofstream    //文件的写操作,将文件写入到存储设备中
fstream     //即可对文件进行读操作,又可对文件进行写操作


1、c++文件的打开方式

#include<fstream>
int main () {
ofstream fout("data.txt");    //打开文件
fout<<"have a good day\n";    //将内容写入文件
fout.close();                 //关闭文件
return 0;
}


解释一下:

ofstream
的定义方式为:

ofstream( const char *filename, openmode mode );


其中,filename指的是文件的路径,可以是相对路径,也可以是绝对路径。

以下定义方式都是正确的:

ofstream fout("data.txt");   //相对路径,在当前目录中即可找到data.txt
ofstream fout("../files/data.txt");  //相对路径,返回上一级文件,在files文件中找到data.txt
ofstream fout("E:/codeblocks code/文件流/files/data.txt");//绝对路径


建议使用相对路径,这样不论你的文件在哪台电脑上都可以正常运行。

mode指的是文件的打开模式,有以下几种方式:

模式说明
ios::in为读取打开文件
ios::out为写入打开文件
ios::app你写入的所有数据将被追加到文件的末尾,此方式使用ios::out
ios::ate你写入的所有数据将被追加到文件的末尾,此方式不使用ios::out
ios::trunc清空文件的所有内容
ios::binary以二进制形式打开一个文件
ios::nocreate如果要打开的文件并不存在,那么以此参数调用open()函数将无法进行。
ios::noreplace如果要打开的文件已存在,试图用open()函数打开时将返回一个错误。
使用方式为:

ofstream fout("data.txt",ios::out);  //以写入方式打开一个文件


注意:

1、如果要写入的文件中原本存在数据,则数据会先被清空。
2、如果文件不存在的话,程序会自动在当前目录文件下创建“data.txt”文件。
3、ios::out可省略不写


还可以几种模式一起使用,中间用‘|’隔开。

ofstream fout("data.txt",ios::out|ios::app);//以追加的形式写入文件


<<
重载运算符输出数据到存储设备,是输入数据的一种方式,后面会介绍其他的几种方式。

close()
方法来关闭文件,实际上是解除该磁盘文件与文件流的关联,每个打开的文件都应当用
close()
方法关闭。

同样的
ifstream
的定义方式为:

ifstream( const char *filename, openmode mode );


这个ifstream类用来读取文件信息,使用方式和ofstream一样,不再多说。

接下来介绍
fstream
类这个类,fstream同时具有
ifstream
ofstream
的特点,可读,可写。

fstream( const char *filename, openmode mode );


用fstream的打开方式为:

#include<iostream>
#include<fstream>
using namespace std;
int main (){
string str;     //str接收文件中的信息
fstream file;   //声明一个fstream类的对象
file.open("data3.txt",ios::in|ios::out);  //用fstream对象 建立与磁盘文件的联系

if(file.is_open())
{
cout<<"The file is open"<<endl;
}

file<<"hello";

file.seekg(ios::beg); // 回到文件首部

file>>str;
cout<<str;

file.close();
}


接下来,我们逐行分析这段代码:

首先可以看到,我们在打开文件时,用了
open()
函数,没错这是打开文件的另一种方式。那么既然可以用直接打开的方式
fstream file("data.txt")
,那为什么还要用
open()
函数呢?这不是多此一举么?其实并不是的。他们的功能虽然相同,但是使用的情景有些不同。例如:我用文件句柄(也就是这里的fstream的实例对象file)打开一个文件后,然后又关闭了这个文件,但我还想用这个文件句柄去打开另一个文件,这时候就用到
open()
函数了。

然后我们又看到file又调用了
is_open()
函数,这个函数是干什么的呢?从文件名我们可以看出,这是一个判断文件是否打开的函数。这个函数又有什么用途呢?想象一下这样一种情况:当我们仅仅只是声明了文件句柄,却没调用
open()
函数,这时候文件还未打开,我们却想当然的用未指向文件的文件句柄去输出/输入文件内容,这时候不就出问题了吗。所以用
is_open()
提前判断一下就可以巧妙的避免这种错误。

之后我们向文件中输出了“hello”。

仔细一看,怎么又出现了一个我没有见过的函数
seekg()
,他是干什么的呢?别着急,在说明
seekg()
是干什么用的之前,先了解一下文件指针的概念。每当我们向文件中输入一个字符,文件指针就会向后移动,指向下一个字符要存储的位置,于是,当我们输入完成后,文件指针就自然指向了文件的末尾位置。这时候虽然我们想输出文件的内容,但文件指针却指向文件末尾,这应该怎么办呢?如果我们想要输出文件的内容,是不是应该将文件指针指向文件的开始位置呢,这就是我们使用
seekg()
函数的作用了。

seekg()函数

用途:移动文件指针的位置,用于输入流

1、istream &seekg( off_type offset, ios::seekdir origin );


该函数用于将文件指针从origin偏移offset个字节的位置上

origin可选:

ios::beg(文件的开始位置)

ios::end(文件的结束位置)

ios::cur(文件的当前位置)

file.seekg(-3,ios::cur) //将文件指针从当前位置向前移动三个字符

2、istream &seekg( pos_type position );


该函数将置文件指针在position位置

file.seekg(2);  //从0开始计数,指向文件第三个字符,输出'llo'


也可以这样使用:

file.seekg(ios::beg);  //将文件指针置于文件首端


他还有个孪生兄弟呢!

seekp();

用途:移动文件位置,用于输出流

ostream &seekp( off_type offset, ios::seekdir origin );
ostream &seekp( pos_type position );


是不是和seekg()定义很像?其实他们的用法也相似。

不同的是:

seekg()用于输入流,在写入文件的时候用

seekp()用于输出流,在读出文件的时候用

好了,总结一下fstream的特点:

用fstream定义文件句柄并且打开文件后,文件指针会指向文件的开始位置,此时,如果你向文件中输入内容的话,会覆盖掉文件原来的内容。比如文件中原来有”helloworld”,然后向文件中输入”aaaaa”,那么此时文件的内容就为”aaaaaworld”,文件的前五个字符被a覆盖了。故在使用它时,一定要注意文件指针的位置,如果想输入内容,请务必将文件指针指向文件末尾,可以通过设置文件的打开方式,或者通过我们刚才讲到的函数来实现。

2、文件的输入/输出方式
(1)文件的输入方式

1、“>>”操作符

“>>”操作符为文件的输入操作符。

2、get()函数

istream &get( char &ch );
istream &get( char *buffer, streamsize num );
istream &get( char *buffer, streamsize num, char delim );
istream &get( streambuf &buffer );
istream &get( streambuf &buffer, char delim );
解释:
+读入一个字符并把它存储在ch,
+读取字符到buffer直到num - 1个字符被读入, 或者碰到EOF或换行标志,
+读取字符到buffer直到已读入num - 1 个字符,或者碰到EOF或delim(delim直到下一次不会被读取),
+读取字符到buffer中,直到碰到换行或EOF,或是读取字符到buffer中,直到碰到换行,EOF或delim。(相反, delim直到下一个get()不会被读取 ).


//读取文件中的‘所有’字符
char ch;
while(fin.get(ch)){
cout<<ch;
}


get()函数可以读取文件中所有的字符,包括回车键(’\n’)。

3、getline()函数

istream &getline( char *buffer, streamsize num );
istream &getline( char *buffer, streamsize num, char delim );
解读:
getline()函数用于输入流,读取字符到buffer中,直到下列情况发生:
+num-1个字符已经读入,
+碰到一个换行标志,
+碰到一个EOF,
+或者,任意地读入,直到读到字符delim。delim字符不会被放入buffer中


//输出文件的所有内容
char p[100];
while(!fin.eof()){
fin.getline(p,100);   //可以根据具体情况,改变数值
cout<<p;
cout<<endl;
}


getline()函数可以整行输出,但无法获取换行符。

(2)文件的输出方式

1、“<<”操作符

“<<”操作符为文件的输出操作符,输出的起点为第一个非空格字符,终点为空格或者回车。

例如:
如果文件内容为:
hello world!
good morning!
输出为:
hello
world!
good
morning!


2、put()函数

char p[]="good morning!hello world!";
int i=0;
while(p[i]!='\0')
{
fout.put(p[i]);
i++;
}


ostream &put( char ch );
函数put()用于输出流,并把字符ch写入流中。


(3)二进制文件的输入/输出方式

1、write()

ostream &write( const char *buffer, streamsize num );


write()函数用于输出流,从buffer中写num个字节到当前输出流中。

2、read()

istream &read( char *buffer, streamsize num );


函数read()用于输入流,在将字符放入buffer 之前从流中读取num 个字节。如果碰到EOF,read()中止,丢弃不论多少个字节已经放入

//以下每个功能均为独立运行
//运行时注意加上注释
int main () {
fstream bin("data.txt",ios::binary|ios::out|ios::in|ios::trunc);
int x=9999,y;
int a[20]={6,3,6,2,3,4,5,6,7,7,7,5,5,4,4,3,3,3,3,4};
char ch='A';
char c[]="have\na\ngood\ntime!";
string str="hello world";

char d[100]={0};
if(!bin.is_open())
{
cout<<"The file is not open!"<<endl;
exit(1);
}

//二进制读写字符串数组
bin.write(c,sizeof(c));
bin.seekg(ios::beg);    //返回文件首端
bin.read(d,sizeof(char)*100);
print(d);
cout<<"end";

//将string字符串写入到文件中
bin.write(str.c_str(),sizeof(char)*(str.size()));
bin.seekg(ios::beg);
bin.read(d,sizeof(char)*20);
cout<<d;

//读写单个字符
char temp;
bin.write(&ch,sizeof(char));
bin.seekg(ios::beg);
bin.read(&temp,sizeof(char));
cout<<temp;

//读写int型数据
bin.write((char*)&x,sizeof(int));
bin.seekg(ios::beg);
bin.read((char*)&y,sizeof(int));
cout<<y;

bin.close();
}


3、文件的其他函数

(1)tellp()

pos_type tellp();


tellp()函数用于输出流中,并返回在流中当前文件指针的位置。

ofstream fout("data.txt");
fout.tellp();    //结果为0,因为此时文件指针指向首端


(2)tellg()

pos_type tellg();


tellg()函数用于输入流,并返回流中文件指针的当前位置。

ifstream fin("data.txt");
fin.tellg();


(3)验证流的状态函数

eof()

到达文件末尾返回true,否则返回false。

bad()

如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

fail()

除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

good()

如果调用以上任何一个函数返回true 的话,此函数返回 false 。

(4)_unlink()函数

删除一个文件。

#include<iostream>
#include<fstream>
#include<io.h>      //_unlink()所要包含的头文件
using namespace std;
int main (){
_unlink("data.txt");
ifstream fin("data.txt");
if(fin.is_open())
{
cout<<"true"<<endl;
}else{
cout<<"false"<<endl;
}
fin.close();
return 0;
}
/*
结果:
false
因为文件被删除了,所以无法打开该文件
*/


最后附上我自己的关于文件的调试代码:

#include<iostream>
#include<fstream>
#include<stdlib.h>  //exit()函数要包含的头文件
using namespace std;

//打印一个字符串数组
void print(char s[]) {
int i=0;
while(s[i]!='\0'){
cout<<s[i];
if(s[i]=='\r')  cout<<"enter"<<endl;
i++;
}
}
// 读取文件数据     ifstream类应用
void input() {
char p[500];
char ch;
string str;

ifstream fin("data1.txt");
//判断文件是否开启
if(!fin.is_open())
{
exit(1);
}

//从文件中第一个非空格字符读取,直到遇到空格或回车结束
while(!fin.eof()){

/*
//一个单词,一个单词的读
fin>>str;
cout<<str<<endl;
*/

/*
//逐个读出
while(fin.get(ch)){    //不能用eof作为文件读取终点的判别条件,最后一个字符会重复一次
cout<<ch;
}
*/

//整行读出
fin.getline(p,100);
cout<<p;
cout<<endl;
}

//  fin>>str;
cout<<str;

fin.close();
}
//将数据写入文件    ofstream类应用
void output() {
//ofstream fout;
//fout.open("../files/data.txt",ios::in);
char p[]="have a good day!";
ofstream fout("data2.txt",ios::trunc);

if(!fout.is_open())
{
exit(1);
}

/*
//逐个字符读入文件
int i=0;
while(p[i]!='\0')
{
fout.put(p[i]);
i++;
}
*/

//一次性写入文件
fout<<p;
fout.close();

};
//读入/读出文件数据  fstream 类应用
void ioput() {
string str;     //接收文件中的信息
fstream file;   //声明一个fstream类的对象
file.open("data3.txt",ios::in|ios::out|ios::app);  //用fstream对象 建立与磁盘文件的联系

if(!file.is_open())
{
cout<<"Error in open a file!"<<endl;
exit(1);
}

file<<"aaaaaa";

file.seekg(ios::beg); // 回到文件首部

file>>str;
cout<<str;

file.close();

}
//以二进制形式,读入读出数据  fsteream
void binaryio() {
fstream bin("data4.txt",ios::binary|ios::out|ios::in|ios::trunc);
int xin99,y;
int a[20]={6,3,6,2,3,4,5,6,7,7,7,5,5,4,4,3,3,3,3,4};
char ch='A';
char c[]="have\na\ngood\ntime!";
string str="hello world";

char d[100]={0};
string s;
if(!bin.is_open())
{
cout<<"The file is not open!"<<endl;
exit(1);
}

//二进制读写字符串数组
bin.write(c,sizeof(c));
bin.seekg(ios::beg);    //返回文件首端
bin.read(d,sizeof(char)*100);
print(d);
cout<<"end";

/*
//将string字符串写入到文件中
bin.write(str.c_str(),sizeof(char)*(str.size()));
bin.seekg(ios::beg);
bin.read(d,sizeof(char)*20);
cout<<d;
*/

/*
//读写单个字符
char temp;
bin.write(&ch,sizeof(char));
bin.seekg(ios::beg);
bin.read(&temp,sizeof(char));
cout<<temp;
*/

/*
//读写int型数据
bin.write((char*)&x,sizeof(int));
bin.seekg(ios::beg);
bin.read((char*)&y,sizeof(int));
cout<<y;
*/

/*
//用put和get函数实现读写二进制文件
int i=0;
while(c[i]!='\0')
{
bin.put(c[i]);
i++;
}
bin.seekg(ios::beg);
char temp;
while(bin.get(temp))    //不能用eof判断文件终点 ,最后一个字符会重复读取一次
{
cout<<temp;
}
*/

/*
//读写单个字符
bin.put(ch);
bin.seekg(ios::beg);
bin.get(ch);
cout<<ch;
*/

/*
//读取整型数组到文件
for(int i=0;i<20;i++)
{
cout<<a[i];
bin.write((char*)&a[i],sizeof(a[i]));
}
bin.read(d,20);
cout<<d;
*/

bin.close();
}

int main () {
//output();
//input();
//ioput();
binaryio();
return 0;
}


#include<iostream>
#include<fstream>
using namespace std;
int main (){
ifstream fin("data.txt");
long length;

fin.seekg(0,ios::end);
length=fin.tellg();
fin.seekg(0,ios::beg);

char *p=new char[length];
fin.read(p,length);
for(int i=0;i<length;i++)
{
cout<<p[i];
}
delete []p;
fin.close();
}


上述代码可以将文件的内容一次全部读出,只是若文件过大,读取的效率较低。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: