C++为不同类型数据的标准输入和输出定义了专门的类库。其中ios为基类,直接派生了4个类,即输入流类istream,输出流类ostream,文件流类fstreambase和字符串流基类strstreambase.
C++系统中的I/O标准类,都定义在iostream.h,fstream.h和strstream.h这三个头文件,各个头文件包含的类如下。
- 进行标准I/O操作时使用iostream.h头文件,它包含有ios,iostream,istream和ostream等类;
- 进行文件I/O操作时使用fstream.h头文件,它包含有fstream,ifstream,ofstream和fstreambase等类;
- 进行串I/O操作时使用头文件strstrea.h头文件,它包含有strstream,istrstream,ostrstream,strstreambase和iostream等类;
流的输入/输出
字符串相加并输出
#include "iostream.h"
#include "strstrea.h"//串I/O操作的头文件
#include "stdafx.h"
/*
istrstream 类的构造函数有两个:
istrstream::istrstream(char *s);
istrstream::istrstream(char *s,int n);
参数说明:
⒈第一个参数 s 是一个字符指针或字符数组,使用该串来初始化要创建的流对象。
⒉ n 表示使用前 n 个字符来构造流对象。
*/
int main()
{
char buf[] = "12345678";
int i,j;
istrstream s1(buf);//用来将文本项转换为变量所需要的内部格式
s1>>i;//s1 = 12345678 将字符串转换为数字(s1是内部字符串格式,通过<<转换为数字)
istrstream s2(buf,3);//前三个字符来构造流对象
s2>>j;//s2 = 123
cout<<i+j<<endl;
return 0;
}
---------
12345801
---------
文件打开
使用文件流与磁盘上的文件进行连接后才能对磁盘上的文件进行操作,这个连接过程称为打开文件。
打开文件的方式有以下两种:
方式一:
创建文件流时利用构造函数打开文件,即在创建流时加入参数: <文件流类><文件流对象名>(<文件名><打开方式>)
打开方式在ios类中定义,有输入方式,输出方式,追加方式等,具体方式如下:
ios类
ios::in | 输入方式打开文件,只能读取,不能改写 |
ios::out | 输出方式打开文件,只能改写,不能读取 |
ios::app | 追加方式打开文件,可以在尾部开始写 |
ios::ate | 打开已存在文件,可读可写 |
ios::binary | 二进制方式打开文件 |
ios::trunc | 打开文件进行写,若文件已存在,则清楚文件中的数据 |
ios::nocreate | 打开已存在文件,若文件不存在,创建失败 |
ios::noreplace | 创建新文件,若文件存在,打开失败,不覆盖 |
ios::in|ios::out | 以读写方式打开文件,对文件可读可写 |
ios::in|ios::binary | 以二进制方式打开文件,进行读操作 |
例:
使用相对路径打开文件进行写操作
ofstream outfile("example.txt",ios::out);
使用绝对路径打开文件进行写操作
ofstream outfile("C::example.txt",ios::out);
方式二:
利用open函数打开磁盘文件:<文件流对象名>.open(<文件名>,<打开方式>);
ifstream infile;
infile.open("example.txt",ios::out);
检测一个文件是否成功打开,采用以下语句:
void open(const char*filename,int mode,int prot=filebuf::openprot);
/*
prot决定文件的访问方式
0:普通文件
1:只读文件
3:隐含文件
4:系统文件
*/
打开文件的同时创建文件
创建文件:
#include<iostream.h>
#include<strstrea.h>
#include<fstream.h>//文件流I/O操作头文件
int main()
{
ofstream ofile;//默认打开方式ios::out|ios::trunk
//文件不存在时,会创建这两个文件,并写入字符串,若文件存在,则直接覆盖原文件
cout<<"Creat file1"<<endl;
ofile.open("test.txt");
if(!ofile.fail())
{
ofile<<"name1"<<" ";
ofile<<"sex1"<<" ";
ofile<<"age1"<<" ";
cout<<"Creat file2"<<endl;
ofile.open("test2.txt");
if(!ofile.fail())
{
ofile<<"name2"<<" ";
ofile<<"sex2"<<" ";
ofile<<"age2"<<" ";
ofile.close();
}
}
return 0;
}
文件的读写
流可以分为3类:即输入流,输出流和输入/输出流
ifstream ifile;//声明一个输入流
ofstream ofile;//声明一个输出流
fstream iofile;//声明一个输入/输出流
ofstream和ifstream类有很多用于磁盘文件管理函数 attach 在打开文件与流之间建立联系 close 刷新为保存的数据后关闭文件 flush 刷新流 open 打开一个文件并与流连接 put 把一个字节写入流中 rdbuf 返回与流连接的filebuf对象 seekp 设置流文件指针位置 setmode 设置流文件为二进制或文本模式 tellp 获取流文件指针位置 write 把一组字节写入流中
fstream成员函数
get(c) | 从文件读取一个字符 |
getline(str,n,'\n') | 从文件读取字符存入字符串str中,知道读取到”n-1“或”\n“时结束 |
peek() | 查找下一个字符,但不读取 |
put(c) | 将一个字符写入文件 |
putback(c) | 对输入流放回一个字符,但不保存 |
cof | 若读取超过cof,返回True |
ignore(n) | 跳过n个字符,参数为空时,表示跳过下一个字符 |
读写文件示例:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int main()
{
char buf[128];
ofstream ofile("test.txt");//声明一个输出流
for(int i = 0;i<5;i++)
{
memset(buf,0,128);//初始化函数,可以将一段连续的内存初始化为0
cin>>buf;//输入字符串
ofile<<buf;//将字符串写入文件
}
ofile.close();
ifstream ifile("test.txt");//声明一个输入流
while(!ifile.eof())//判断是否是文件末尾
{
char ch;
ifile.get(ch);//从文件读取一个字符串
if(!ifile.eof())
{
cout<<ch;
}
}
cout<<endl;
ifile.close();
return 0;
}
写文本文件
文本文件时程序开发中经常用到的文件,使用记事本就可以打开文本文件。上面代码示例使用了ifstream和ofstream创建并写入了文件,下面代码示例主要应用fstream写入文本文件。
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int main()
{
char buf[128];
fstream file("test.txt",ios::out);//声明一个输入/输出流,输出方式打开文件,只能改写
//fail()用来判断一个流是否“坏”掉了,当输入流读取失败时,会将字符放在原处,等待下一次读取;
if(!file.fail())
{
cout<<"start write"<<endl;
file<<"name"<<" ";
file<<"sex"<<" ";
file<<"age"<<endl;
}
else
cout<<"can not open"<<endl;
file.close();
return 0;
}
程序通过fstream类的构造函数打开文本文件test.txt,然后向文本文件写入字符串。
读取文本文件
读取文本文件的代码示例:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int main()
{
fstream file("test.txt",ios::in);//输入方式打开文件,只能读取
//fail()用来判断一个流是否“坏”掉了,当输入流读取失败时,会将字符放在原处,等待下一次读取;
if(!file.fail())
{
while(!file.eof())//判断是否文件末尾
{
char buf[128];
file.getline(buf,128);//从文件中读取字符存到buf中
if(file.tellg()>0)//返回当前定位指针的位置,也代表着输入流的大小
{
cout<<buf;
cout<<endl;
}
}
}
else
cout<<"can not open"<<endl;
file.close();
return 0;
}
二进制文件的读写
文本文件中的数据都是ASCII码,若要读取图片内容,就不可以使用读取文本文件的方法,通过二进制方式读取文件,需要使用ios::binary模式。
代码示例:使用read读取文件
#include<iostream.h>
#include<fstream.h>
#include<string.h>
int main()
{
char buf[50];
fstream file;
//先以二进制方式写入文件
file.open("test.dat",ios::out);
cout<<"写入数据:"<<endl;
for(int i = 0;i<2;i++)
{
memset(buf,0,50);
cin>>buf;
file.write(buf,50);
file<<endl;
}
file.close();
cout<<"读取数据:"<<endl;
//再通过fstream类以二进制方式读取
file.open("test.dat",ios::in);
while(!file.eof())
{
memset(buf,0,50);
file.read(buf,50);
if(file.tellg()>0)
cout<<buf;
}
cout<<endl;
file.close();
return 0;
}
----------
写入数据:
Hello
World
读取数据:
Hello
World
----------
文件的复制 :代码示例
#include<iostream>
#include<fstream.h>
#include<iomanip.h>
#include<string.h>
int main()
{
ifstream infile;//输入流
ofstream outfile;//输出流
char name[20];
char c;
cout<<"请输入文件:"<<"\n";
cin>>name;
infile.open(name);
if(!infile)
{
cout<<"文件打开失败!";
exit(1);
}
strcat(name,"副本");//把两个字符串合并,就是副本文件名字
cout<<"start copy"<<endl;
outfile.open(name);//打开副本
if(!outfile)
{
cout<<"无法复制";
exit(1);
}
while(infile.get(c))//把原文件的内容读到c中
{
outfile<<c;//输出到副本中
}
cout<<"end"<<endl;
infile.close();
outfile.close();
return 0;
}
文件指针移动操作
在读写文件的过程中,有时用户不需要对整个文件进行读写,而是对指定位置的一段数据进行读写,需要通过移动文件指针来完成。
ios类中提供了以下成员函数来检测或设置流的状态
int rdstate();//返回当前流的状态
/*
badbit 发生致命的错误
eofbit 已经发现EOF
failbit 一个非致命性错误已经发生
goodbit 没有发生错误
*/
int eof();//判断其是否读到文件结尾
int fail();//判断一个流是否“坏”掉了
int bad();
int good();
文件的追加
当写入一部分数据后再根据条件向文件中追加写入:
#include<iostream>
#include<fstream.h>
#include<iomanip.h>
#include<string.h>
//方法一
int main()
{
ofstream ofile("test.txt",ios::app);
//ios::app 如果没有文件,生成空文件;
//如果有文件,在文件尾追加
if(!ofile.fail())
{
cout<<"start write"<<endl;
ofile<<endl;
ofile<<"Mary ";
ofile<<"girl ";
ofile<<"20";
}
else
cout<<"can not open";
return 0;
}
---------------
Hello World
Happy everyday
Mary girl 20
---------------
//方法二
#include<iostream>
#include<fstream.h>
#include<iomanip.h>
#include<string.h>
int main()
{
fstream iofile("test.txt",ios::in|ios::out);//定义一个输入输出流
if(!iofile.fail())
{
iofile.seekp(0,ios::end);//第一个参数是设置偏移,第二个参数是设置读写的位置
//即从头开始移动到尾部,作用是保存到文件(p=put)
iofile<<endl;
iofile<<"我是新加入的";
iofile.seekg(0);//放置指针从0开始,作用是从文件中读取(g=get)
int i = 0;
char data[20];
while(!iofile.eof() && i<sizeof(data))
{
iofile.get(data[i++]);
}
cout<<data;
}
return 0;
}
----------------
Hello World
Happy everyday
Mary girl 20
我是新加入的
----------------
文件结尾的判断:除了利用eof()判断文件是否结束,还有其他方法,例如get()方法,当文件指向文件末尾,get()方法获取不到数据就返回-1,也可以作为判断结束的方法。
在指定位置读写文件:
常用文件指针函数
seekg | 相对位置用于输入文件中的指针移动 |
seekp | 相对位置用于输出文件中的指针移动 |
tellg | 用于查找输出文件中的文件指针位置 |
tellp | 用于查找输出文件中的文件指针位置 |
ios::beg | 相对位置取值:文件头部 |
ios::end | 相对位置取值:文件尾部 |
ios::cur | 相对位置取值:文件指针的当前位置 |
删除文件:remove()函数,是系统提供的函数,可以删除指定的磁盘文件。