打开和关闭文件
要执行文件的输入输出,须做以下几件事:
(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
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
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
#include
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;
}
void open(const unsigned char*,int mode,int access=filebuf::openprot);
const unsigned char*:文件名,为无符号的常字符,即常字符串。若输入为字符串对象,必须将该字符对象转换为C语言风格,即将字符串对象转换为字符数组。
文件打开
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: 用于输入。文件以输入方式打开
ios::out: 用于输出。文件以输出方式打开。
ios::app: 以追加的方式打开文件。主要用于文件的写操作。如果文件不存在,则创建文件。如果文件存在,则不会删除文件中的内容
int main(){
fstream f;
f.open("result.txt",ios::app);
f.put('d');
f.seekp(ios::beg);//移动文件写指针到文件开始
f.put(‘e’); //文件写操作仍在文件尾部
return 0;
}
ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性。
int main()
{
fstream f;
f.open("result1.txt",ios::ate|ios::in);
if(!f)
cout<<"Error!";
return 0;
}
关闭文件
关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志, 切断流对象和外部文件的连接。若流对象的生存期没有结束,可以重用 ,当一个流对象的生存期结束,系统也会自动关闭文件 。
ofstream ofile ; //创建输入文件流
ofile . open ( “myfile1” ) ; //ofile流与文件“myfile1”相关联
… //访问文件“myfile1”
ofile . close ( ) ; //关闭文件“myfile1”
ofile . open ( “myfile2” ); //重用ofile流
#include
#include
using namespace std;
int main ( ){
ofstream ost ;
ost . open ( "d:\\my1.dat ") ;
ost << 20 << endl ;
ost << 30.5 << endl ;
ost . close ( ) ;
ifstream ist ( "d:\\my1.dat" ) ;
int n ;
double d ;
ist >> n >> d ;
cout << n << endl << d << endl ;
}
文本文件
文本文件用默认方式打开
文本文件用文件流对象(文本文件流)进行读/写操作
文本文件是顺序存取文件
通常一个逻辑记录用换行符分隔;数据项之间可以用空白符、换行符、制表符等分隔
文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是不同的
只能顺序访问每一条记录
//把一个整数、一个浮点数和一个串写到文件 d:\test 中
#include
#include
using namespace std;
int main(){
ofstream out( "d:\\test" ) ;
if ( !out )
{return 0; }
out << 10 << " " << 123.45 << " " ;
out << "\nThis is a short text file." ;
out.close () ;
return 1 ;
}
//从文件 d:\test 中读出一个整数、一个浮点数、一个字符和两个串
#include
#include < fstream >
using namespace std;
int main (){
char ch ;
int i ;
float f ;
char str1 [ 10 ] , str2 [ 10 ] ;
ifstream in ( "d:\\test" ) ;
if ( ! in ) {return 0 ; }
in >> i >> f >> ch >> str1 >> str2 ;
cout << i << " " << f << " " << ch << '\n' ;
cout << str1 << str2 << endl ;
in.close () ;
}
//把文件 d:\test 复制到文件 d:\testnew 中
#include
#include
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" ;
}
//建立一个包含学生学号、姓名、成绩的文本文件
#include
#include
using namespace std;
int main(){
char fileName[30];
string name;
int number , score ;
ofstream outstuf ;
cin >> fileName ;
outstuf.open( fileName, ios::out ) ;
if ( !outstuf )
{ cerr << "File could not be open." << endl ; abort(); }
outstuf << "学生成绩文件\n" ;
while( cin >> number >> name >> score ) {
outstuf << number << ' ' << name << ' ' << score << '\n' ;
cout << "? " ;
}
outstuf.close() ;
}
//读文本文件。在屏幕显示学生记录,以及最高分数、最低分数和平均分数
#include
#include
using namespace std;
int main(){
string name , s ;
int number , score ; int n = 0, max, min, total = 0 ; double ave;
ifstream instuf( "d:\\students.txt", ios::in ) ;
if ( !instuf )
{abort(); }
instuf.getline( s, 80 ) ;
while( instuf >> number >> name >> score ) {
cout << number << '\t' << name << '\t' << score << '\n' ;
if (n==0) { max = min = score; }
else
{
if ( score > max ) max = score ;
if ( score < min ) min = score ; }
total+=score; n++;
}
ave = double(total) / n ;
cout << max << endl << min << endl
<< ave << endl;
instuf.close() ;
}
//利用类对文件操作进行封装,实现学生信息文件内容的显示,文件中添加记录等基本的操作
#include
#include
#include
using namespace std;
struct student{
string name ;
int number , score ;
};
class FileOperation{
string filename;
student record[100]; //假设文件中存储的及记录个数不超过100
int num;//存储记录的个数
public:
FileOperation();
void display();
void append();
~FileOperation();
};
FileOperation::FileOperation(){
cin>>filename;
ifstream instuf( filename.c_str(), ios::in ) ;
num=0;
if ( !instuf )
{exit(0); }
instuf >> record[num].number >> record[num].name >> record[num].score;
while(!instuf.eof() ) {
num++;
instuf >> record[num].number >> record[num].name >> record[num].score;
}
instuf.close();
}
void FileOperation::display()
{
cout<<"number"<<"\t"<<"name"<<"\t"<<"score"<<endl;
for(int i=0;i<num;i++)
cout << record[i].number << '\t' << record[i].name << '\t' << record[i].score << '\n' ;
}
void FileOperation::append()
{
cin>>record[num].number>>record[num].name>>record[num].score;
num++;
}
FileOperation::~FileOperation(){
ofstream outstuf ;
outstuf.open( filename.c_str(), ios::out ) ;
if ( !outstuf )
abort();
for(int i=0;i<num;i++)
outstuf << record[i].number << ' ' << record[i].name << ' ' << record[i].score << '\n' ;
outstuf.close() ;
}
int main()
{
FileOperation f;
f.append();
f.display();
return 0;
}
二进制文件
二进制文件以基本类型数据在内存的二进制表示形式存放数据,不对写入或读出的数据做格式转换 ==
二进制文件的读写方式由程序控制
== 打开二进制文件用binary方式
==二进制文件是随机存取文件 ==
二进制文件是顺序存取文件
文件中只存储了数据,没有存储记录的逻辑结构
每条记录的长度是相同的
可以随机访问每一条记录
用read()函数和write()函数读写文件 (成块的读写)
可以成块(若干字节)进行读写操作
读写的过程中不进行转换(不存在二进制流到文本流得转换)
适用于二进制文件。
read()和write()原型如下:
istream &read(unsigned char* buf,int num);
ostream &write(const unsigned char* buf,int num);
//用write()函数向文件test中写入整数与双精度数。
#include
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
#include
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;
}
fin.read(内存地址 char,字节数);*
注意:这里的char需要做类型转换,reinterpret_cast
fout.write(内存地址 char,字节数);*
在c语言中,fread(内存地址,单位大小,总个数,文件)和fwrite是将数据在文件和内存中间移动处理,对应c++的为fin.read(内存地址 注意这里需要强制性类型转换,字节数)和fout.write(内存地址,字节数)。
fin.getcount() 最后一次read操作读到几个字节
bool eof();
如果达到相关联的文件末尾,eof()函数返回true,否则返回false。
文件的随机读写
在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 () ;
作用:返回读指针当前所指位置值
put指针的操作:
ostream& seekp(streampos pos); //移动put指针到 pos位置
ostream& seekp(streamoff offset ,ios::seek_dir dir);
long tellp(); //获取 put 指针的值
其中,参数dir表示文件指针的起始位置,off表示相对于这个起始位置的位移量。dir的取值有以下3种情况:
①ios::beg 从文件头开始,文件指针移动由off指定的距离。
②ios::cur 从当前位置开始,文件指针移动由off指定的距离。
③ios::end 从文件尾开始,文件指针移动由off指定的距离。
例:datafile.seekp(-20L,ios::cur); //表示将文件定位指针从当前位置向文件头部方向移20个字节。
#include
void main() {
// 假如我们已经在test_file.txt中存有了“Hello”的内容
ifstream File("test_file.txt");
char arr[10];
File.read(arr,10);
// 由于Hello占5个字符,因此这里将返回5
cout << File.tellg() << endl;
File.close();
}
get指针的操作:
istream& seekg(streampos pos); //指针直接定位
istream& seekg(streamoff off,ios::seek_dir dir); //指针相对定位
long tellg();// 获取get指针的值
其中,参数dir表示文件指针的起始位置,off表示相对于这个起始位置的位移量。dir的取值有以下3种情况:
①ios::beg 从文件头开始,文件指针移动由off指定的距离。
②ios::cur 从当前位置开始,文件指针移动由off指定的距离。
③ios::end 从文件尾开始,文件指针移动由off指定的距离。
例:datafile.seekg(-20L,ios::cur); //表示将文件定位指针从当前位置向文件头部方向移20个字节。
//将文件test中第五个字符修改成X 。
#include
#include
void main(void){
fstream fs;
fs.open("d:\\test",ios::in| ios::out); // 以读写方式打开文件
if (fs.fail())
cout<<"open file errer!";
else {
fs.seekp(4,ios::beg); // 设置写指针
fs.put('X');
char contents[10];
fs.seekg(0,ios::beg); // 设置读指针
fs.get(contents,10);
cout<<contents;
}
fs.close();
}
命令行参数
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
//建立一个Win32控制台程序,生成exe文件名为testmain.exe,
//放到D:\盘上,用命令行方式执行
#include
using namespace std;
int main(int argc, char* argv[])
{
int i;
cout<<"argc="<<argc<<endl;
for(i=0; i<argc; i++)
cout<<argv[i]<<endl;
return 0;
}