C++文件读写详解ofstreamifstreamfstream及C++ string类.docx
《C++文件读写详解ofstreamifstreamfstream及C++ string类.docx》由会员分享,可在线阅读,更多相关《C++文件读写详解ofstreamifstreamfstream及C++ string类.docx(16页珍藏版)》请在冰豆网上搜索。
![C++文件读写详解ofstreamifstreamfstream及C++ string类.docx](https://file1.bdocx.com/fileroot1/2022-11/24/841c7b54-1956-4321-bbcf-f2aded8ade42/841c7b54-1956-4321-bbcf-f2aded8ade421.gif)
C++文件读写详解ofstreamifstreamfstream及C++string类
在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,fstream,以前粗略知道其用法和含义,在看了几位大牛的博文后,进行整理和总结:
这里主要是讨论fstream的内容:
[java]viewplaincopyprint?
1.#include
2.ofstream //文件写操作 内存写入存储设备
3.ifstream //文件读操作,存储设备读区到内存中
4.fstream //读写操作,对打开的文件可进行读写操作
#include
ofstream//文件写操作内存写入存储设备
ifstream//文件读操作,存储设备读区到内存中
fstream//读写操作,对打开的文件可进行读写操作
1.打开文件
在fstream类中,成员函数open()实现打开文件的操作,从而将数据流和文件进行关联,通过ofstream,ifstream,fstream对象进行对文件的读写操作
函数:
open()
[cpp]viewplaincopyprint?
1. Times New Roman; font-size:
16px;">
2.public member function
3.
4.void open ( const char * filename,
5. ios_base:
:
openmode mode = ios_base:
:
in | ios_base:
:
out );
6.
7.void open(const wchar_t *_Filename,
8. ios_base:
:
openmode mode= ios_base:
:
in | ios_base:
:
out,
9. int prot = ios_base:
:
_Openprot);
10.
11.
publicmemberfunction
voidopen(constchar*filename,
ios_base:
:
openmodemode=ios_base:
:
in|ios_base:
:
out);
voidopen(constwchar_t*_Filename,
ios_base:
:
openmodemode=ios_base:
:
in|ios_base:
:
out,
intprot=ios_base:
:
_Openprot);
参数:
filename 操作文件名
mode 打开文件的方式
prot 打开文件的属性 //基本很少用到,在查看资料时,发现有两种方式
打开文件的方式在ios类(所以流式I/O的基类)中定义,有如下几种方式:
ios:
:
in
为输入(读)而打开文件
ios:
:
out
为输出(写)而打开文件
ios:
:
ate
初始位置:
文件尾
ios:
:
app
所有输出附加在文件末尾
ios:
:
trunc
如果文件已存在则先删除该文件
ios:
:
binary
二进制方式
这些方式是能够进行组合使用的,以“或”运算(“|”)的方式:
例如
[cpp]viewplaincopyprint?
1.ofstream out;
2.out.open("Hello.txt", ios:
:
in|ios:
:
out|ios:
:
binary) //根据自己需要进行适当的选取
ofstreamout;
out.open("Hello.txt",ios:
:
in|ios:
:
out|ios:
:
binary)//根据自己需要进行适当的选取
打开文件的属性同样在ios类中也有定义:
0
普通文件,打开操作
1
只读文件
2
隐含文件
4
系统文件
对于文件的属性也可以使用“或”运算和“+”进行组合使用,这里就不做说明了。
很多程序中,可能会碰到ofstreamout("Hello.txt"),ifstreamin("..."),fstreamfoi("...")这样的的使用,并没有显式的去调用open()函数就进行文件的操作,直接调用了其默认的打开方式,因为在stream类的构造函数中调用了open()函数,并拥有同样的构造函数,所以在这里可以直接使用流对象进行文件的操作,默认方式如下:
[cpp]viewplaincopyprint?
1. Times New Roman; font-size:
16px;">
2.ofstream out("...", ios:
:
out);
3.ifstream in("...", ios:
:
in);
4.fstream foi("...", ios:
:
in|ios:
:
out);
5.
6.
ofstreamout("...",ios:
:
out);
ifstreamin("...",ios:
:
in);
fstreamfoi("...",ios:
:
in|ios:
:
out);
当使用默认方式进行对文件的操作时,你可以使用成员函数is_open()对文件是否打开进行验证
2.关闭文件
当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。
成员函数close(),它负责将缓存中的数据排放出来并关闭文件。
这个函数一旦被调用,原先的流对象就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程所访问了。
为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close。
3.文本文件的读写
类ofstream,ifstream和fstream是分别从ostream,istream和iostream中引申而来的。
这就是为什么fstream的对象可以使用其父类的成员来访问数据。
一般来说,我们将使用这些类与同控制台(console)交互同样的成员函数(cin和cout)来进行输入输出。
如下面的例题所示,我们使用重载的插入操作符<<:
[cpp]viewplaincopyprint?
1. // writing on a text file
2. #include
3. int main () {
4. ofstream out("out.txt");
5. if (out.is_open())
6. {
7. out << "This is a line.\n";
8. out << "This is another line.\n";
9. out.close();
10. }
11. return 0;
12. }
13.//结果:
在out.txt中写入:
14.This is a line.
15.This is another line
//writingonatextfile
#include
intmain(){
ofstreamout("out.txt");
if(out.is_open())
{
out<<"Thisisaline.\n";
out<<"Thisisanotherline.\n";
out.close();
}
return0;
}
//结果:
在out.txt中写入:
Thisisaline.
Thisisanotherline
从文件中读入数据也可以用与cin>>的使用同样的方法:
[cpp]viewplaincopyprint?
1.// reading a text file
2. #include
3. #include
4. #include
5.
6. int main () {
7. char buffer[256];
8. ifstream in("test.txt");
9. if (!
in.is_open())
10. { cout << "Error opening file"; exit
(1); }
11. while (!
in.eof() )
12. {
13. in.getline (buffer,100);
14. cout << buffer << endl;
15. }
16. return 0;
17. }
18. //结果 在屏幕上输出
19. This is a line.
20. This is another line
//readingatextfile
#include
#include
#include
intmain(){
charbuffer[256];
ifstreamin("test.txt");
if(!
in.is_open())
{cout<<"Erroropeningfile";exit
(1);}
while(!
in.eof())
{
in.getline(buffer,100);
cout<}
return0;
}
//结果在屏幕上输出
Thisisaline.
Thisisanotherline
上面的例子读入一个文本文件的内容,然后将它打印到屏幕上。
注意我们使用了一个新的成员函数叫做eof,它是ifstream从类ios中继承过来的,当到达文件末尾时返回true。
状态标志符的验证(Verificationofstateflags)
除了eof()以外,还有一些验证流的状态的成员函数(所有都返回bool型返回值):
∙bad()
如果在读写过程中出错,返回true。
例如:
当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。
∙fail()
除了与bad()同样的情况下会返回true以外,加上格式错误时也返回true,例如当想要读入一个整数,而获得了一个字母的时候。
∙eof()
如果读文件到达文件末尾,返回true。
∙good()
这是最通用的:
如果调用以上任何一个函数返回true的话,此函数返回false。
要想重置以上成员函数所检查的状态标志,你可以使用成员函数clear(),没有参数。
获得和设置流指针(getandputstreampointers)
所有输入/输出流对象(i/ostreamsobjects)都有至少一个流指针:
∙ifstream,类似istream,有一个被称为getpointer的指针,指向下一个将被读取的元素。
∙ofstream,类似ostream,有一个指针putpointer,指向写入下一个元素的位置。
∙fstream,类似iostream,同时继承了get和put
我们可以通过使用以下成员函数来读出或配置这些指向流中读写位置的流指针:
∙tellg()和tellp()
这两个成员函数不用传入参数,返回pos_type类型的值(根据ANSI-C++标准),就是一个整数,代表当前get流指针的位置(用tellg)或put流指针的位置(用tellp).
∙seekg()和seekp()
这对函数分别用来改变流指针get和put的位置。
两个函数都被重载为两种不同的原型:
seekg(pos_typeposition);
seekp(pos_typeposition);
使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。
要求传入的参数类型与函数tellg和tellp的返回值类型相同。
seekg(off_typeoffset,seekdirdirection);
seekp(off_typeoffset,seekdirdirection);
使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。
它可以是:
ios:
:
beg
从流开始位置计算的位移
ios:
:
cur
从流指针当前位置开始计算的位移
ios:
:
end
从流末尾处开始计算的位移
流指针get和put的值对文本文件(textfile)和二进制文件(binaryfile)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。
由于这个原因,建议对以文本文件模式打开的文件总是使用seekg和seekp的第一种原型,而且不要对tellg或tellp的返回值进行修改。
对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。
以下例子使用这些函数来获得一个二进制文件的大小:
[cpp]viewplaincopyprint?
1.// obtaining file size
2. #include
3. #include
4.
5. const char * filename = "test.txt";
6.
7. int main () {
8. long l,m;
9. ifstream in(filename, ios:
:
in|ios:
:
binary);
10. l = in.tellg();
11. in.seekg (0, ios:
:
end);
12. m = in.tellg();
13. in.close();
14. cout << "size of " << filename;
15. cout << " is " << (m-l) << " bytes.\n";
16. return 0;
17. }
18.
19. //结果:
20. size of example.txt is 40 bytes.
//obtainingfilesize
#include
#include
constchar*filename="test.txt";
intmain(){
longl,m;
ifstreamin(filename,ios:
:
in|ios:
:
binary);
l=in.tellg();
in.seekg(0,ios:
:
end);
m=in.tellg();
in.close();
cout<<"sizeof"<cout<<"is"<<(m-l)<<"bytes.\n";
return0;
}
//结果:
sizeofexample.txtis40bytes.
4.二进制文件
在二进制文件中,使用<<和>>,以及函数(如getline)来操作符输入和输出数据,没有什么实际意义,虽然它们是符合语法的。
文件流包括两个为顺序读写数据特殊设计的成员函数:
write和read。
第一个函数(write)是ostream的一个成员函数,都是被ofstream所继承。
而read是istream的一个成员函数,被ifstream所继承。
类fstream的对象同时拥有这两个函数。
它们的原型是:
write(char*buffer,streamsizesize);
read(char*buffer,streamsizesize);
这里buffer是一块内存的地址,用来存储或读出数据。
参数size是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。
[cpp]viewplaincopyprint?
1.// reading binary file
2. #include
3. #include
4.
5. const char * filename = "test.txt";
6.
7. int main () {
8. char * buffer;
9. long size;
10. ifstream in (filename, ios:
:
in|ios:
:
binary|ios:
:
ate);
11. size = in.tellg();
12. in.seekg (0, ios:
:
beg);
13. buffer = new char [size];
14. in.read (buffer, size);
15. in.close();
16.
17. cout << "the complete file is in a buffer";
18.
19. delete[] buffer;
20. return 0;
21. }
22. //运行结果:
23. The complete file is in a buffer
//readingbinaryfile
#include
#include
constchar*filename="test.txt";
intmain(){
char*buffer;
longsize;
ifstreamin(filename,ios:
:
in|ios:
:
binary|ios:
:
ate);
size=in.tellg();
in.seekg(0,ios:
:
beg);
buffer=newchar[size];
in.read(buffer,size);
in.close();
cout<<"thecompletefileisinabuffer";
delete[]buffer;
return0;
}
//运行结果:
Thecompletefileisinabuffer
5.缓存和同步(BuffersandSynchronization)
当我们对文件流进行操作的时候,它们与一个streambuf类型的缓存(buffer)联系在一起。
这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。
例如,对于一个输出流,每次成员函数put(写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。
当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。
这个过程称为同步(synchronization),它会在以下任一情况下发生:
∙当文件被关闭时:
在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。
∙当缓存buffer满时:
缓存Buffers有一定的空间限制。
当缓存满时,它会被自动同步。
∙控制符明确指明:
当遇到流中某些特定的控制符时,同步会发生。
这些控制符包括:
flush和endl。
∙明确调用函数sync():
调用成员函数sync()(无参数)可以引发立即同步。
这个函数返回一个int值,等于-1表示流没有联系的缓存或操作失败。
标准C++中的string类的用法总结
相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?
的确,MFC中的CString类使用起来真的非常的方便好用。
但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?
答案是肯定的。
也许有人会说,即使不用MFC框架,也可以想办法使用MFC中的API,具体的操作方法在本文最后给出操作方法。
其实,可能很多人很可能会忽略掉标准C++中string类的使用。
标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用。
现将具体用法的一部分罗列如下,只起一个抛砖引玉的作用吧,好了,废话少说,直接进入正题吧!
要想使用标准C++中string类,必须要包含
#include//注意是,不是,带.h的是C语言中的头文件
using std:
:
string;
using std:
:
wstring;
或
usingnamespacestd;
下面你就可以使用string/wstring了,它们两分别对应着char和wchar_t。
string和wstring的用法是一样的,以下只用string作介绍:
string类的构造函数:
string(constchar*s); //用c字符串s初始化
string(intn,charc); //用n个字符c初始化
此外,string类还支持默认构造函数和复制构造函数,如strings1;strings2="hello";都是正确的写法。
当构造的string太长而无法表达时会抛出length_error异常;
string类的字符操作:
constchar&operator[](intn)const;