C++之文件IO操作流
来源:互联网 发布:读取acess数据 编辑:程序博客网 时间:2024/05/22 03:52
1.在C++中对文件进行操作分为以下几个步骤:(1)建立文件流对象;(2)打开或建立文件;(3)进行读写操作;(4)关闭文件;用于文件IO操作的流类主要有三个fstream(输入输出文件流),ifstream(输入文件流)和ofstream(输出文件流);而这三个类都包含在头文件fstream中,所以程序中对文件进行操作必须包含该头文件。首先建立流对象,然后使用文件流类的成员函数open打开文件,即把文件流对象和指定的磁盘文件建立关联。成员函数open的一般形式为:
文件流对象.open(文件名,使用方式);
其中文件名可以包括路径(如:e:\c++\file.txt),如果缺少路径,则默认为当前目录。使用方式则是指文件将被如何打开。以下就是文件的部分使用方式,都是ios基类中的枚举类型的值:
此外打开方式有几个注意点:
(1)因为nocreate和noreplace,与系统平台相关密切,所以在C++标准中去掉了对它的支持。
(2)每一个打开的文件都有一个文件指针,指针的开始位置由打开方式指定,每次读写都从文件指针的当前位置开始。每读一个字节,指针就后移一个字节。当文件指针移到最后,会遇到文件结束符EOF,此时流对象的成员函数eof的值为非0值,表示文件结束。
(3)用in方式打开文件只能用于输入数据,而且该文件必须已经存在。
(4)用app方式打开文件,此时文件必须存在,打开时文件指针处于末尾,且该方式只能用于输出。
(5)用ate方式打开一个已存在的文件,文件指针自动移到文件末尾,数据可以写入到其中。
如果文件需要用两种或多种方式打开,则用"|"来分隔组合在一起。除了用open成员函数打开文件,还可以用文件流类的构造函数来打开文件,其参数和默认值与open函数完全相同。比如:文件流类 stream(文件名,使用方法);如果文件打开操作失败,open函数的返回值为0,用构造函数打开的话,流对象的值为0。所以无论用哪一种方式打开文件,都需要在程序中测试文件是否成功打开。
在每次对文件IO操作结束后,都需要把文件关闭,那么就需要用到文件流类的成员函数close,一般调用形式:流对象.close();关闭实际上就是文件流对象和磁盘文件失去关联。
2.介绍完文件的打开和关闭,接下来说说文件的读写。我将分别从文本文件读写和二进制文件的读写来介绍。其实文件的读写是十分容易的。流类库中的IO操作<<、>>、put、get、getline、read和write都可以用于文件的输入输出。
(1)文本文件的读写:
写文件: #include "stdafx.h" #include <iostream> #include <fstream> int main() { //打开文件 std::ofstream file("file.txt",std::ios::out|std::ios::ate); if(!file) { std::cout<<"不可以打开文件"<<std::endl; exit(1); } //写文件 file<<"hello c++!\n"; char ch; while(std::cin.get(ch)) { if(ch=='\n') break; file.put(ch); } //关闭文件 file.close(); return0;}读文件file.txt:
#include "stdafx.h"#include <iostream>#include <fstream> int main(){ //打开文件 std::ifstream rfile("file.txt",std::ios::in); if(!rfile) { std::cout<<"不可以打开文件"<<std::endl; exit(1); } //读文件 char str[100]; rfile.getline(str,100);//读到'\n'终止 std::cout<<str<<std::endl; char rch; while(rfile.get(rch))//文件指针指向字符‘\n’的下一个 { std::cout.put(rch); } std::cout<<std::endl; //关闭文件 rfile.close(); return0;}
读出显示字符:
其实建立ifstream类和ofstream类的对象时,ios:in和ios:out可以省略,因为ifstream类默认为ios:in,ofstream类默认为ios:out;
(2)最初设计流的目的是用于文本,因此在默认情况下,文件用文本方式打开。在以文本模式输出时,若遇到换行符"\n"(十进制为10)则自动扩充为回车换行符(十进制为13和10)。所以,如果我们输入的整数10,那么在文件输出时会转化为13和10,然而这并不是我们所需要的。为了解决这样的问题,就要采用而二进制模式,使其所写的字符不转换。在对二进制文件进行IO操作时,打开文件时要指定方式ios::binary,即以二进制形式传送和存储。接下来我用read函数和write函数来对二进制文件进行读写。在示例描述之前先简单介绍一下这两个函数:
read函数常用格式为:文件流对象.read(char *buf,int len);
write函数常用格式为:文件流对象.write(const char *buf,int len);
两者格式上差不多,第一个参数是一个字符指针,用于指向读入读出数据所放的内存空间的其实地址。第二个参数是一个整数,表示要读入读出的数据的字节数。以下是二进制文件的读写的示例:
定义一个精灵类(用于文件数据处理):
class Sprite{private: std::string profession;//职业 std::string weapon;//武器 static int count;//个数public: Sprite(){} Sprite(std::string profession,std::string weapon):profession(profession),weapon(weapon) {} void showSprite();//显示精灵信息};int Sprite::count=0; void Sprite::showSprite(){ ++count; std::cout<<"精灵"<<count<<"职业:"<<profession<<"武器:"<<weapon<<std::endl;}写文件:
#include "stdafx.h"#include <iostream>#include <fstream>#include <string>int main(){ //建立对象数组 Sprite sprites[3]={ Sprite("法师","魔杖"), Sprite("战士","屠龙宝刀"), Sprite("道士","倚天剑") }; //打开文件 std::ofstream file("file.dat",std::ios::ate|std::ios::binary); if(!file) { std::cout<<"文件打开失败!"; abort();//等同于exit } //写文件 for(int i=0;i<3;i++) file.write((char*) &sprites[i],sizeof(sprites[i])); //关闭文件 file.close(); return0;}读文件file.dat:
#include "stdafx.h"#include <iostream>#include <fstream>#include <string> int main(){ //建立对象数组 Sprite rsprites[3]; //打开文件 std::ifstream rfile("file.dat",std::ios::binary); if(!rfile) { std::cout<<"文件打开失败!"; return1;//等同于exit } //读文件 for(int i=0;i<3;i++) { rfile.read((char*) &rsprites[i],sizeof(rsprites[i])); rsprites[i].showSprite(); } //关闭文件 rfile.close(); return0;}
读出显示字符:
在read函数还是write函数里都要把数据转化为char*类型,代码中sizeof函数是用于确定要读入读出的字节数。
在文件结束处有个标志位EOF,在用文件流读取文件时,使用成员函数eof()(函数原型:int eof())可以检测到结束符。如果该函数返回值为非零,则表示到达文件末尾。返回零则表示未达到文件末尾。
(3)前面所介绍的文件都是按顺序来读取的的,C++中又提供了针对于文件读写指针的相关成员函数,使得我们可以在IO流中随意移动文件指针,从而对文件的进行随机地读写。类istream针对读指针提供3个成员函数:
tellg()//返回输入文件读指针的当前位置;
seekg(文件中的位置)//将输入文件中的读指针移动到指定位置
seekg(位移量,参照位置)//以参照位置为基准移动若干字节
其中参照位置是枚举值:
beg//从文件开头计算要移动的字节数
cur//从文件指针的当前位置计算要移动的字节数
end//从文件的末尾计算要移动的字节数
如果参照位置省略,则默认为beg.而类ostream针对写指针提供的3个成员函数:
tellp()//返回输出文件写指针的当前位置;
seekp(文件中的位置)//将输出文件中的写指针移动到指定位置
seekp(位移量,参照位置)//以参照位置为基准移动若干字节
现在我对上一示例中读取二进制文件代码稍作更改:
#include "stdafx.h"#include <iostream>#include <fstream>#include <string> int main(){ //建立对象数组 Sprite rsprites[3]; //打开文件 std::ifstream rfile("file.dat",std::ios::binary); if(!rfile) { std::cout<<"文件打开失败!"; return1;//等同于exit } //读文件 for(int i=0;i<3;i++) { rfile.read((char*) &rsprites[i],sizeof(rsprites[i])); rsprites[i].showSprite(); } Sprite rsprite;//建立对象 std::cout<<"改变读取顺序:"<<std::endl; rfile.seekg(sizeof(Sprite)*2,std::ios::beg);//读取精灵道士信息 rfile.read((char*) &rsprite,sizeof(Sprite)); rsprite.showSprite(); rfile.seekg(-int(sizeof(Sprite)*2),std::ios::end);//读取精灵战士信息 rfile.read((char*) &rsprite,sizeof(Sprite)); rsprite.showSprite(); rfile.seekg(-int(sizeof(Sprite)*2),std::ios::cur);//读取精灵法师信息 rfile.read((char*) &rsprite,sizeof(Sprite)); rsprite.showSprite(); //关闭文件 rfile.close(); return0;}
=================================
补充:
open函数的参数定义了文件的打开模式。总共有如下模式
属性列表
ios::in 读
ios::out 写
ios::app 从文件末尾开始写
ios::binary 二进制模式
ios::nocreate 打开一个文件时,如果文件不存在,不创建文件。
ios::noreplace 打开一个文件时,如果文件不存在,创建该文件
ios::trunc 打开一个文件,然后清空内容
ios::ate 打开一个文件时,将位置移动到文件尾
Notes
默认模式是文本
默认如果文件不存在,那么创建一个新的
多种模式可以混合,用|(按位或)
文件的byte索引从0开始。(就像数组一样)
我们也可以调用read函数和write函数来读写文件。
文件指针位置在c++中的用法:
ios::beg 文件头
ios::end 文件尾
ios::cur 当前位置
- C++IO之文件操作
- C#IO流文件操作
- C标准库之文件IO操作
- c++IO之标准设备操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之文件IO操作流
- C++之 文件IO操作流
- IO流之文件读写操作
- io流操作之文件重命名代码
- IO流之文件的操作
- java中的io流之文件操作
- 跟我学android应用开发 之 如何创建选项卡(Tab)
- 蛇形矩阵
- 键盘添加工具条
- PE文件之PE映像尺寸详解
- 子网划分、变长子网掩码(VLSM)和TCP/IP排错(理论指导实践)
- C++之文件IO操作流
- IOS开发缓存机制之—内存缓存机制
- IOS开发缓存机制之—本地缓存机制
- How to install OWLNext 6.1x
- Eclipse中使用自己的makefile管理工程
- 移动文件指针细节
- core dump
- 二值图像连通域标记算法与代码
- Ant的构建java工程