??xml version="1.0" encoding="utf-8" standalone="yes"?>
1、插入器(<<)
向流输出数据。比如说pȝ有一个默认的标准输出?cout)Q一般情况下是指的昄器,所以,cout<<"Write Stdout"<<'n';pC把字符?Write Stdout"和换行字W?'n')输出到标准输出流?
2、析取器(>>)
从流中输入数据。比如说pȝ有一个默认的标准输入?cin)Q一般情况下是指的键盘Q所以,cin>>x;pCZ标准输入中d一个指定类?卛_量x的类?的数据?
在C++中,Ҏ(gu)件的操作是通过stream的子cfstream(file stream)来实现的Q所以,要用q种方式操作文gQ就必须加入头文件fstream.h。下面就把此cȝ文g操作q程一一道来?
一、打开文g
在fstreamcMQ有一个成员函数open()Q就是用来打开文g的,其原型是Q?
void open(const char* filename,int mode,int access);
参数Q?
filenameQ?要打开的文件名
modeQ?要打开文g的方?
accessQ?打开文g的属?
打开文g的方式在cios(是所有流式I/Ocȝ基类)中定义,常用的值如下:(x)
ios::appQ?以追加的方式打开文g
ios::ateQ?文g打开后定位到文g,ios:app包含有此属?
ios::binaryQ?以二q制方式打开文gQ缺省的方式是文本方式。两U方式的区别见前?
ios::inQ?文g以输入方式打开
ios::outQ?文g以输出方式打开
ios::nocreateQ?不徏立文Ӟ所以文件不存在时打开p|
ios::noreplaceQ不覆盖文gQ所以打开文g时如果文件存在失?
ios::truncQ?如果文g存在Q把文g长度设ؓ(f)0
可以用“或”把以上属性连接v来,如ios::out|ios::binary
打开文g的属性取值是Q?
0Q普通文Ӟ打开讉K
1Q只L?
2Q隐含文?
4Q系l文?
可以用“或”或者?”把以上属性连接v?Q如3?|2是以只d隐含属性打开文g?
例如Q以二进制输入方式打开文gc:config.sys
fstream file1;
file1.open("c:config.sys",ios::binary|ios::in,0);
如果open函数只有文g名一个参敎ͼ则是以读/写普通文件打开Q即Q?
file1.open("c:config.sys");<=>file1.open("c:config.sys",ios::in|ios::out,0);
另外Qfstreamq有和open()一L(fng)构造函敎ͼ对于上例Q在定义的时侯就可以打开文g了:(x)
fstream file1("c:config.sys");
特别提出的是Qfstream有两个子c:(x)ifstream(input file stream)和ofstream(outpu file stream)Qifstream默认以输入方式打开文gQ而ofstream默认以输出方式打开文g?
ifstream file2("c:pdos.def");//以输入方式打开文g
ofstream file3("c:x.123");//以输出方式打开文g
所以,在实际应用中Q根据需要的不同Q选择不同的类来定义:(x)如果想以输入方式打开Q就用ifstream来定义;如果想以输出方式打开Q就用ofstream来定义;如果想以输入/输出方式来打开Q就用fstream来定义?
二、关闭文?
打开的文件用完成后一定要关闭Qfstream提供了成员函数close()来完成此操作Q如Qfile1.close();把file1相连的文件关闭?
三、读写文?
d文g分ؓ(f)文本文g和二q制文g的读取,对于文本文g的读取比较简单,用插入器和析取器可以了Q而对于二q制的读取就要复杂些Q下要就详细的介l这两种方式
1、文本文件的d
文本文g的读写很单:(x)用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开Qfile2以输出打开。示例如下:(x)
file2<<"I Love You";//向文件写入字W串"I Love You"
int i;
file1>>i;//从文件输入一个整数倹{?
q种方式q有一U简单的格式化能力,比如可以指定输出?6q制{等Q具体的格式有以下一?
操纵W?功能 输入/输出
dec 格式化ؓ(f)十进制数值数?输入和输?
endl 输出一个换行符q刷新此?输出
ends 输出一个空字符 输出
hex 格式化ؓ(f)十六q制数值数?输入和输?
oct 格式化ؓ(f)八进制数值数?输入和输?
setpxecision(int p) 讄点数的_ֺ位数 输出
比如要把123当作十六q制输出Qfile1<<hex<<123;要把3.1415926?位精度输出:(x)file1<<setpxecision(5)<<3.1415926?
2、二q制文g的读?
①put()
put()函数向流写入一个字W,其原型是ofstream &put(char ch)Q用也比较单,如file1.put('c');是向流写一个字W?c'?
②get()
get()函数比较灉|Q有3U常用的重蝲形式Q?
一U就是和put()对应的Ş式:(x)ifstream &get(char &ch);功能是从中d一个字W,l果保存在引用ch中,如果到文件尾Q返回空字符。如file2.get(x);表示从文件中d一个字W,q把d的字W保存在x中?
另一U重载Ş式的原型是:(x) int get();q种形式是从中q回一个字W,如果到达文g,q回EOFQ如x=file2.get();和上例功能是一L(fng)?
q有一UŞ式的原型是:(x)ifstream &get(char *buf,int num,char delim='n')Q这UŞ式把字符d?buf 指向的数l,直到d?num 个字W或遇到了由 delim 指定的字W,如果没?delim q个参数Q将使用~省值换行符'n'。例如:(x)
file2.get(str1,127,'A');//从文件中d字符到字W串str1Q当遇到字符'A'或读取了127个字W时l止?
③读写数据块
要读写二q制数据块,使用成员函数read()和write()成员函数Q它们原型如下:(x)
read(unsigned char *buf,int num);
write(const unsigned char *buf,int num);
read()从文件中d num 个字W到 buf 指向的缓存中Q如果在q未d num 个字W时到了文件尾Q可以用成员函数 int gcount();来取得实际读取的字符敎ͼ?write() 从buf 指向的缓存写 num 个字W到文g中,值得注意的是~存的类型是 unsigned char *Q有时可能需要类型{换?
例:(x)
unsigned char str1[]="I Love You";
int n[5];
ifstream in("xxx.xxx");
ofstream out("yyy.yyy");
out.write(str1,strlen(str1));//把字W串str1全部写到yyy.yyy?
in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整数Q注意类型{?
in.close();out.close();
四、检EOF
成员函数eof()用来(g)是否到达文件尾Q如果到达文件尾q回?|否则q回0。原型是int eof();
例:(x) if(in.eof())ShowMessage("已经到达文g!");
五、文件定?
和C的文件操作方式不同的是,C++ I/Opȝ理两个与一个文件相联系的指针。一个是L针,它说明输入操作在文g中的位置Q另一个是写指针,它下ơ写操作的位|。每ơ执行输入或输出Ӟ相应的指针自动变化。所以,C++的文件定位分位置和写位置的定位,对应的成员函数是 seekg()?seekp()Qseekg()是设|读位置Qseekp是设|写位置。它们最通用的Ş式如下:(x)
istream &seekg(streamoff offset,seek_dir origin);
ostream &seekp(streamoff offset,seek_dir origin);
streamoff定义?iostream.h 中,定义有偏U量 offset 所能取得的最大|seek_dir 表示Ud的基准位|,是一个有以下值的枚DQ?
ios::begQ?文g开?
ios::curQ?文g当前位置
ios::endQ?文gl尾
q两个函C般用于二q制文gQ因为文本文件会(x)因ؓ(f)pȝ对字W的解释而可能与预想的g同?
例:(x)
file1.seekg(1234,ios::cur);//把文件的L针从当前位置向后U?234个字?
file2.seekp(1234,ios::beg);//把文件的写指针从文g开头向后移1234个字?
如果vc~程的话最好用CFilecȝ更加方便于文件操?br />
序论
我曾发表q文件输入输出的文章Q现在觉得有必要再写一炏V文?I/O 在C++中比烤蛋p简单多了?在这文章里Q我?x)详l解释ASCII和二q制文g的输入输出的每个l节Q值得注意的是Q所有这些都是用C++完成的?
一、ASCII 输出
Z使用下面的方? 你必d含头文g<fstream.h>(译者注Q在标准C++中,已经使用<fstream>取代<fstream.h>Q所有的C++标准头文仉是无后缀的?。这?<iostream.h>的一个扩展集, 提供有缓冲的文g输入输出操作. 事实? <iostream.h> 已经?lt;fstream.h>包含? 所以你不必包含所有这两个文g, 如果你想昑ּ包含他们Q那随便你。我们从文g操作cȝ设计开? 我会(x)讲解如何q行ASCII I/O操作?如果你猜?fstream," 恭喜你答对了Q?但这文章介l的Ҏ(gu),我们分别使用"ifstream"??"ofstream" 来作输入输出?br />如果你用q标准控制台?cin"??"cout," 那现在的事情对你来说很简单?我们现在开始讲输出部分Q首先声明一个类对象。ofstream fout;
q就可以了,不过你要打开一个文件的? 必须像这栯用ofstream::open()?
fout.open("output.txt");
你也可以把文件名作ؓ(f)构造参数来打开一个文?
ofstream fout("output.txt");
q是我们使用的方? 因ؓ(f)q样创徏和打开一个文件看h更简? Z说一? 如果你要打开的文件不存在Q它?x)?f)你创Z? 所以不用担心文件创建的问题. 现在p出到文gQ看h?cout"的操作很像?对不了解控制台输?cout"的h, q里有个例子?
int num = 150;
char name[] = "John Doe";
fout << "Here is a number: " << num << "\n";
fout << "Now here is a string: " << name << "\n";
现在保存文gQ你必须关闭文gQ或者回写文件缓? 文g关闭之后׃能再操作? 所以只有在你不再操作这个文件的时候才调用它,它会(x)自动保存文g?回写~冲Z(x)在保持文件打开的情况下保存文g, 所以只要有必要׃用它?回写看v来像另一ơ输? 然后调用Ҏ(gu)关闭。像q样Q?
fout << flush; fout.close();
现在你用文本~辑器打开文gQ内容看h是这P(x)
Here is a number: 150 Now here is a string: John Doe
很简单吧! 现在l箋文g输入, 需要一Ҏ(gu)? 所以先认你已l明白了操作,?"<<" ?>>" 比较熟?zhn)? 因ؓ(f)你接下来q要用到他们。l?
二、ASCII 输入
输入?cin" 很? 和刚刚讨论的输出很? 但你要考虑几g事情。在我们开始复杂的内容之前, 先看一个文本:(x)
12 GameDev 15.45 L This is really awesome!
Z打开q个文gQ你必须创徏一个in-stream对象,?像这栗?
ifstream fin("input.txt");
现在d前四? 你还记得怎么?<<" 操作W往里插入变量和符号吧Q好,??"<<" (插入)?操作W之后,?>>" (提取) 操作W? 使用Ҏ(gu)是一L(fng). 看这个代码片D?
int number;
float real;
char letter, word[8];
fin >> number; fin >> word; fin >> real; fin >> letter;
也可以把q四行读取文件的代码写ؓ(f)更简单的一行?
fin >> number >> word >> real >> letter;
它是如何q作的呢? 文g的每个空白之? ">>" 操作W会(x)停止d内容, 直到遇到另一?gt;>操作W? 因ؓ(f)我们d的每一行都被换行符分割开(是空白字W?, ">>" 操作W只把这一行的内容d变量。这是q个代码也能正常工作的原因。但是,可别忘了文g的最后一行?
This is really awesome!
如果你想把整行读入一个char数组, 我们没办法用">>"?操作W,因ؓ(f)每个单词之间的空|I白字符Q会(x)中止文g的读取。ؓ(f)了验证:(x)
char sentence[101]; fin >> sentence;
我们惛_含整个句? "This is really awesome!" 但是因ؓ(f)I白, 现在它只包含?This". 很明? 肯定有读取整行的Ҏ(gu), 它就是getline()。这是我们要做的?
fin.getline(sentence, 100);
q是函数参数. W一个参数显然是用来接受的char数组. W二个参数是在遇到换行符之前Q数l允许接受的最大元素数? 现在我们得到了想要的l果Q“This is really awesome!”?br />你应该已l知道如何读取和写入ASCII文g了。但我们q不能Ş休,因ؓ(f)二进制文件还在等着我们?
三、二q制 输入输出
二进制文件会(x)复杂一? 但还是很单的?首先你要注意我们不再使用插入和提取操作符(译者注Q?lt;< ?>> 操作W?. 你可以这么做Q但它不?x)用二进制方式读写。你必须使用read() 和write() Ҏ(gu)d和写入二q制文g. 创徏一个二q制文g, 看下一行?
ofstream fout("file.dat", ios::binary);
q会(x)以二q制方式打开文g, 而不是默认的ASCII模式。首先从写入文g开始。函数write() 有两个参数?W一个是指向对象的charcd的指? W二个是对象的大(译者注Q字节数Q?Z说明Q看例子?
int number = 30; fout.write((char *)(&number), sizeof(number));
W一个参数写?(char *)(&number)". q是把一个整型变量{为char *指针。如果你不理解,可以立刻阅C++的书c,如果有必要的话。第二个参数写作"sizeof(number)". sizeof() q回对象大小的字节数. 是q样!
二进制文件最好的地方是可以在一行把一个结构写入文件?如果_(d)你的l构?2个不同的成员?用ASCII?文gQ你不得不每ơ一条的写入所有成员?但二q制文g替你做好了?看这个?
struct OBJECT { int number; char letter; } obj;
obj.number = 15;
obj.letter = ‘M?
fout.write((char *)(&obj), sizeof(obj));
q样写入了整个l构! 接下来是输入. 输入也很单,因ؓ(f)read()?函数的参数和 write()是完全一L(fng), 使用Ҏ(gu)也相同?
ifstream fin("file.dat", ios::binary); fin.read((char *)(&obj), sizeof(obj));
我不多解释用? 因ؓ(f)它和write()是完全相同的。二q制文g比ASCII文g? 但有个缺Ҏ(gu)无法用文本编辑器~辑?接着, 我解释一下ifstream 和ofstream 对象的其他一些方法作为结?
四、更多方?br /> 我已l解释了ASCII文g和二q制文g, q里是一些没有提?qing)的底层?gu)?
(g)查文?br />你已l学?x)了open() 和close() Ҏ(gu), 不过q里q有其它你可能用到的Ҏ(gu)?br />Ҏ(gu)good() q回一个布?yu)(dng)|表示文g打开是否正确?br />cM的,bad() q回一个布?yu)(dng)DC文件打开是否错误?如果出错Q就不要l箋q一步的操作了?br />最后一个检查的Ҏ(gu)是fail(), 和bad()有点怼, 但没那么严重?
L?br />Ҏ(gu)get() 每次q回一个字W?br />Ҏ(gu)ignore(int,char) 跌一定数量的某个字符, 但你必须传给它两个参数。第一个是需要蟩q的字符数?W二个是一个字W? 当遇到的时候就?x)停止?例子,
fin.ignore(100, ‘\n?;
?x)蟩q?00个字W,或者不?00的时候,跌所有之前的字符Q包?‘\n’?br />Ҏ(gu)peek() q回文g中的下一个字W? 但ƈ不实际读取它。所以如果你用peek() 查看下一个字W? 用get() 在peek()之后dQ会(x)得到同一个字W? 然后Ud文g计数器?br />Ҏ(gu)putback(char) 输入字符, 一ơ一? 到流中。我没有见到q它的用,但这个函数确实存在?
写文?br />只有一个你可能?x)关注的?gu).?那就?put(char), 它每ơ向输出中写入一个字W?
打开文g
当我们用q样的语法打开二进制文?
ofstream fout("file.dat", ios::binary);
"ios::binary"是你提供的打开选项的额外标? 默认? 文g以ASCII方式打开, 不存在则创徏, 存在p? q里有些额外的标志用来改变选项?
ios::app d到文件尾
ios::ate 把文件标志放在末而非起始?
ios::trunc 默认. 截断q覆写文件?
ios::nocreate 文g不存在也不创建?
ios::noreplace 文g存在则失败?
文g状?br /> 我用q的唯一一个状态函数是eof(), 它返回是否标志已l到了文件末?我主要用在@环中?例如, q个代码断统计小写‘e?在文件中出现的次数?
ifstream fin("file.txt");
char ch; int counter;
while (!fin.eof()) {
ch = fin.get();
if (ch == ‘e? counter++;
}
fin.close();
我从未用q这里没有提到的其他Ҏ(gu)?q有很多Ҏ(gu)Q但是他们很被使用。参考C++书籍或者文件流的帮助文档来了解其他的方法?
l论
你应该已l掌握了如何使用ASCII文g和二q制文g。有很多Ҏ(gu)可以帮你实现输入输出Q尽很有Z用他们?我知道很多h不熟(zhn)文件I/O操作Q我希望q篇文章对你有所帮助?每个人都应该知道. 文gI/Oq有很多显而易见的Ҏ(gu),?例如包含文g <stdio.h>. 我更喜欢用流是因Z们更单?所有读了这文章的人好q? 也许以后我还?x)?f)你们写些东西。