11.5 文件处理
要执行文件的输入输出,须做以下几件事:
(1) 在程序中包含头文件<fstream>
;
(2) 建立文件流。建立文件流的过程就是定义流类的对象,例如:
ifstream in;
ofstream out;
fstream both;
分别定义了输入流对象in;输出流对象out,输入输出流对象both。
(3) 使用open()函数打开文件,也就是使某一文件与上面的某一流相联系。
open()函数是上述三个流类的成员函数,其原型是在fstream.h中定义的, 原型为:
void open(const unsigned char,int mode,int access=filebuf::openprot);
(4)对open结果进行检查(检查打开操作是否成功。可省略,但不推荐。)
(5)进行读写。在建立(或打开)的文件上执行所要求的输入或输出操作;
(6)关闭文件流对象。
文件读写例子
#include<fstream>
using namespace std;
int main(){
ofstream fout;
fout.open("f:\\test.txt",ios::out);//建立文件信息区
if (! fout.is_open()){ cout<<"Cannot open output file\n,"; return 1;}
fout<<10<<" "<<123.456<<" "<<"This is a text file.\n";
fout.close();
return 0;
}
a.is_open()函数, 该函数用来判断文件打开是否成功(建立文件信息区)。也可以通过判断流的状态 if(fout.fail()): if(! fout.good())
还可以采用:if(! fout):测定 对象 a 是否 建立/存在(fstream 类对象不能使用这种方式)
文件读写例子
#include<fstream>
using namespace std;
int main(){
ofstream fout;char filename[20];cin>>filename;
fout.open(filename,ios::out);//建立文件信息区
if (! fout.is_open()){ cout<<"Cannot open output file\n,"; return 1;}
fout<<10<<" "<<123.456<<" "<<"This is a text file.\n";
fout.close();
return 0;
}
文件读写例子
#include<fstream>
#include <string>
using namespace std;
int main(){
ofstream fout;string filename;cin>>filename;
fout.open(filename.c_str(),ios::out);//将字符串对象转化为字符数组
if (! fout.is_open()){ cout<<"Cannot open output file\n,"; return 1;}
fout<<10<<" "<<123.456<<" "<<"This is a text file.\n";
fout.close();
return 0;
}
1.文件打开
open()函数原型在fstream中定义,函数原型如下:
void open (char* filename, int mode, int access=0);
第一个参数用于传递文件名;
第二个参数mode值表示文件的使用方式;
第三个参数打开文件的共享方式
filebuf::openprot; //默认的兼容共享方式(与MS_DOS文件兼容)
filebuf::sh_none; //独占,不共享
filebuf::sh_read; //读共享
filebuf::sh_write; //写共享
ios::in = 0x01,//供读, (ifstream默认的打开方式)
ios::out = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式)
ios::ate = 0x04, //文件打开时,指针在文件尾部。可改变指针的位置,常和in、out联合使用
ios::app = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后
ios::trunc = 0x10, //在读写前先将文件长度截断为0(默认)
ios::binary = 0x80 //二进制格式文件
ios::in: 用于输入。文件以输入方式打开
ifstream流类的默认打开方式
文件存在,打开文件;
文件不存在,打开失败。
ios::out: 用于输出。文件以输出方式打开。
ofstream流类的默认打开方式
如果文件存在,打开文件,并清空原文件中的内容。
如果文件不存在,则创建文件。
如果文件路径错误,创建流对象操作失败。
ios::app: 以追加的方式打开文件。主要用于文件的写操作。如果文件不存在,则创建文件。如果文件存在,则不会删除文件中的内容
在该模式下,不管文件指针处于何处,新写入的内容永远在文件尾。
int main(){
fstream f;
f.open("result.txt",ios::app);
f.put('d');
f.seekp(ios::beg);//移动文件写指针到文件开始
f.put(‘e’); //文件写操作仍在文件尾部
return 0;
}
2.关闭文件
关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志,
切断流对象和外部文件的连接
若流对象的生存期没有结束,可以重用
当一个流对象的生存期结束,系统也会自动关闭文件
ofstream ofile ;
ofile . open ( "myfile1" ) ;
……
ofile . close ( ) ;
ofile . open ( "myfile2" );
11.5.3 文本文件
文本文件用默认方式打开
文本文件用文件流对象(文本文件流)进行读/写操作
文本文件是顺序存取文件
struct student //定义记录,一条记录反映了一个对象的基本信息
{
int number ;
string name ;
int score ;
};
通常一个逻辑记录用换行符分隔;数据项之间可以用空白符、换行符、制表符等分隔
文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是不同的
只能顺序访问每一条记录(数据对象)
把文件 d:\test 复制到文件 d:\testnew 中
#include<iostream>
#include <fstream>
using namespace std;
int main ( ){
char ch ;
ifstream f1 ( "d:\\test" ) ;
if ( !f1 ) {return 0; }
ofstream f2 ( "d:\\testnew" ) ;
if ( !f2 ) {return 0; }
while ( f1 && f1.get(ch) ) f2.put( ch ) ;//读一个字符,写一个字符
f1.close () ;
f2.close () ;
cout << "It is over !\n" ;
}
11.5.4 二进制文件
- 二进制文件以基本类型数据在内存的二进制表示形式存放数据,不对写入或读出的数据做格式转换
- 二进制文件的读写方式由程序控制
- 打开二进制文件用binary方式
- 二进制文件是随机存取文件
struct student //定义记录,一条记录反映了一个对象的基本信息
{
int number ;
char name[20] ;//不用string是因为string不是定长的
int score ;
};
文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是相同的
可以随机访问每一条记录
用read()函数和write()函数读写文件 (成块的读写)
可以成块(若干字节)进行读写操作
读写的过程中不进行转换(不存在二进制流到文本流得转换)
适用于二进制文件。
read()和write()原型如下:
istream &read(unsigned char* buf,int num);//(内存中的位置,连续处理多少个字节)
ostream &write(const unsigned char* buf,int num);
例 用write()函数向文件test中写入整数与双精度数。
#include<fstream.h>
int main(){
ofstream out(“f:\\test.dat”,ios::binary);
if (!out) {return 1; }
int i=12340; double num=100.45;
out.write((char *) &i,sizeof(int));
out.write((char *) &num,sizeof(double));
out.close();
ifstream in("f:\\test.dat");
if (!in) {return 1; }
int j;double d;
in.read((char *)&j,sizeof(int));
in.read((char *)&d,sizeof(double));
cout<<j<<" "<<d<<endl;
in.close();return 0; }
例 从键盘输入若干个学生的有关数据,然后把它们转存到磁盘文件上去。
#include <fstream>
#include <iostream>
using namespace std;
class Student{
char name[10]; int num; int age; char addr[20];
public:
friend ostream & operator <<(ostream &out,Student &obj){ out<<obj.name<<"\t"<<obj.num<<"\t"<<obj.age<<"\t"<<obj.addr<<endl;
return out; }
friend istream& operator >>(istream & in,Student obj) {
in>>obj.name>>obj.num>>obj.age>>obj.addr;
return in; }
};
class Student_list
{
Student stud[1000];
int number;
public:
Student_list();
void input();
void display() ;
~Student_list();
};
Student_list::Student_list(){
fstream fin("stu.dat",ios::in|ios::binary);
int i=0;
number=i;
if(!fin) return ;
fin.read ((char *)&stud[i],sizeof(Student));
while(!fin.eof())//判断是否到文件尾
{
i++;
fin.read ((char *)&stud[i],sizeof(Student));
}
number=i;
fin.close ();
return ;
}
void Student_list::input()
{
cin>>stud[number++];
}
void Student_list::display()
{
for (int i=0;i<number; i++)
cout<<stud[i];
return ;
}
Student_list::~Student_list()
{
fstream fout("stu.dat",ios::out|ios::binary);
if(!fout)
{
cout<<"cannot open file\n";
return;
}
for(int i=0;i<number;i++)
fout.write((char *)&stud[i],sizeof(Student));
//fout.write((char *) stud, number*sizeof(Student));
fout.close();
}
int main()
{
Student_list s_list;
while(1)
{
s_list.input();
cout<<"Continue(Y/N)?";
char ch;
cin>>ch;
if(ch=='N' || ch=='n')
break;
}
s_list.display();
return 0;
}
文件的随机读写
在C++的I/O系统中有个文件指针,它有两个名字。
其中一个名字叫get指针,用于指出下一次输入操作的位置;
另一个名字叫做put指针,用于指出下一次输出操作的位置
istream 类操作流读指针的成员函数
istream & istream :: seekg ( long pos) ;
作用:读指针从流的起始位置向后移动由pos指定字节
istream & istream :: seekg ( long off, ios::seek_dir ) ;
作用:读指针从流的seek_dir位置移动 off 指定字节
ios::seek_dir 值:
cur 相对于当前读指针所指定的当前位置
beg 相对于流的开始位置
end 相对于流的结尾处
enum ios::seek_dir { beg = 0 ; cur = 1 , end = 2 }
istream & istream :: tellg () ;
作用 返回读指针当前所指位置值
命令行参数
C++程序的main函数可以添加参数,即main函数的原型为:
int main(int argc, char* argv[]);
argc:接受字符串的个数
argv[]:接受程序作为命令行执行时输入的字符串
例如,若exe文件名为testmain,在命令窗口输入:
testmain aaa bbb ccc
则有: argv[0] 为 “testmain”
argv[1] 为 “aaa”
argv[2] 为 “bbb”
argv[3] 为 “ccc”
argc 为 4