1. 文件的概述
文件,一般是指相关数据的集合。计算机中的数据都是以文件的形式放置在外部介质(譬如磁盘、光盘和U盘)中的。
操作系统是以文件为单位对数据进行管理的,也就是说:
-
想找外部介质上的数据,必须先按文件名找到所指定的文件,然后再从该文件中读取数据
-
想向外部介质上存储数据,必须先建立一个文件(以文件名标识你的数据要存到介质的哪个地方)然后把数据输出到那里
1.1 文件的分类 之一
-
外部文件
是指磁盘文件、光盘文件、U盘文件。目前使用最为广泛的是磁盘文件,在程序中对光盘文件和U盘文件的访问与磁盘文件相同。
-
内部文件
是指程序运行中的文件,更正式的称谓是“文件流对象”。
对用户来说,常用 的文件有两大类:
-
程序文件(program file)如C++的源代码文件(.cpp)、目标文件(.obj)、可执行文件(.exe)等
-
数据文件(data file) 在程序运行时,常常需要将一些数据(运行的最终结果或者中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机的内存。这种磁盘文件称为数据文件。
程序中的输入和输出的对象就是数据文件。
1.2 文件的分类之二
-
ASCII文件:也叫文本文件、字符文件,每个字节存放一个ASCII代码,表示一个字符
-
二进制文件:也叫内部格式文件、字节文件,把内存中的数据按其在内存中的存储格式原样输出到磁盘上存放
对于字符信息,其在内存中是以ASCII代码的形式存放的,因此,无论用ASCII文件输出还是二进制文件输出,其数据形式都是一样的,不会出现“乱码”现象。
对于数值数据和其他数据,二者是不同的,例如有一个int类型的数据100000,其在内存中占4个字节,如果按内存格式输出,在磁盘文件中占4个字节,如果将它转化为ASCII码形式输出(便于人类观看),则要占6个字节。
“类型”规定了你如何去解释那串二进制代码!
1.3. C++如何使用文件
输入和输出都是针对内存而言的 |
内存里面的内容 在C++看来也应该是流(类比于工厂中要用的水或排除出的水),鄙人将其理解字节流。
所以要将文件里面的内容弄到内存中去,或者要将内存中的内容弄到文件里面去,就必须有一根管子连接。
管子的一端始终接着内存,另外一端接着文件(这一段可以改变,也就是说,你可以先接这个文件,再接那个文件)
1.4.文件流类和文件流对象(管子类和管子对象)
-
输出文件流:内存-------->外部文件
-
输入文件流:外部文件--------->内存
每个文件流都有一个内存缓冲区与之对应。
C++的I/O库中定义了3个专门用于文件操作的“管子类”:
-
ifstream
-
ofstream
-
fstream
1 |
|
2.文件的打开与关闭
2.1 打开文件 open( )
三种“管子”对象都能够打开文件,
-
ifstream类的实例 打开文件进行写
-
ofstream类的实例 打开文件进行读
-
fstream类的实例 打开文件可读可写
1 | // example |
文件输入输出方式设置值
方式 | 作用 |
---|---|
ios::in | 以输入方式打开文件,准备读文件 |
ios::out | 以输出方式打开文件(这是默认方式)如果已有此文件,则将原来的内容清空后;文件不存在,则创建之 |
ios::app | 以输出方式打开文件,写入的数据添加再文件末尾;文件不存在,则创建之 |
ios::binary | 以二进制方式打开文件,如果不指定这个,则默认为ASCII方式(即文本模式) |
ios::trunc | 打开一个文件,如果文件存在,则删除其中全部数据,如不存在,则新建新文件 |
ios::ate | 打开一个已有文件,文件指针指向文件末尾 |
2.2 关闭文件close( )
1 | outfile.close(); |
当C++程序终止时,它会自动关闭刷新所有的流,释放所有分配的内存,并关闭所有打开的文件,但一个合格的程序员应该在程序终止前自己关闭所有你打开的文件(你得为你所作的负责)。
所谓“关闭”,实际上是解除“管子”和磁盘文件的关联,让“管子”的一端不和磁盘文件相连了。这样,原来的设置方式也会失效。
3. 文件的读写
如果文件中的每1字节中均以ASCII代码形式存放数据,即1字节存放一个字符,这个文件就是ASCII文件(或称为文本文件)。
二进制文件在操作时,数据不做任何的变换,直接传送,因此它又被称为内存数据的映像文件。因为文件中的信息不是字符数据,而是字节中的二进制形式的信息,因而它也被称为字节文件。
3.1 文本文件的写入
【example 1 start】
1 |
|
运行上面的代码:
得到1.txt文件,其内容如下:
看看1.txt的属性,应该为9个字节(3+2+2+2)
解释:
-
3 321 共3个字符占3个字节
-
2 ax 共2个字符占2个字节
-
2 你 共1个字符,由于是中文,所以占2个字节
-
2 0D 0A 对应于\r \n,即后面的endl 共占2个字节
看看1.txt在二进制模式下的内容:
思考:
1 | cin>>a;// 用户在输入a时超过了int类型的范围会怎么样?后面的string类型能写入文件嘛? |
answer: 会将int的最大数写入文件,后面的string类型写不进文件。
【example 1 end】
3.2 文本文件的读出
【example 2 start】
1 |
|
【example 2 end】
3.3 二进制文件的写入
【example 3 start】
1 |
|
运行上面的代码:
得到2.txt文件,其内容会有乱码,如下所示:
分析得到其大小应该为240个字节(80*3)(注意内存对齐现象)
查看2.txt的属性:
【example 3 end】
3.4 二进制文件的读出
【example 4 start】
1 |
|
运行上述代码:
【example 4 end】
3.5 文件的数据定位
磁盘文件中有一个文件指针,用来指明当前应进行的读写的位置。
-
在输入时每读入1个字节,指针就后移1个字节
-
在输出时每输出1个字节,指着就后移1个字节
对应二进制文件,允许对指针进行控制,所以提供了一些函数供我们使用。
成员函数 | 作用 |
---|---|
gcount( ) | 返回最后一次输入所读入的字节数 |
tellg( ) | 返回输入文件指针的当前位置 |
seekg(文件中的位置) | 将输入文件中指针移到指定的位置 |
seekg(位移量,参照位置) | 以参照位置为基础移动若干字节 |
tellp( ) | 返回输出文件指针的当前位置 |
seekp(文件中的位置) | 将输出文件中指针移到指定的位置 |
seekp(位移量,参照位置 ) | 以参照位置为基础移动若干字节 |
参照位置可取:
-
ios::beg
-
ios::cur
-
ios::end