C++文件的读写操作详解

在程序设计中,文件常用的操作不外乎——打开、读、写、流指针操作、关闭。在回答问题时,却发现很多道友没有真正掌握这些简单的操作。为此,博主就文件的一系列操作进行详细介绍,供道友们学习。

一、文件的相关概念

(一)文件及文件类型
计算机上的文件其实是数据的集合,对文件的读写其实是对数据的读写。
文件可以大致分为两种:文本文件和二进制文件。  
1、文本文件:它的每一个字节存放的是一个ASCII码,代表一个字符。
2、二进制文件:将内存中的数据按照其在内存中的存储形式原样存放在磁盘上。
文本文件用记事本打开,显示的是字符,如图(1)。而用记事本打开一个二进制文件则显示的是一堆乱码,如图(2)。
在这里插入图片描述
在这里插入图片描述
(二)文件的路径
1、文件的路径分隔符
(1)正斜杠(左斜杠),符号是"/"
(2)反斜杠(右斜杠),符号是"",但是在c++编程中,由于反斜杠还有转义字符的意思,改写成双反斜杠"\"。
总的来说,在C++编程中,路径符号只有"/“和”\"。

2、文件的绝对路径——英文的双引号
定义:文件在硬盘上真正存在的路径。
例1:a.txt文件是在D盘的wamp目录下的img子目录中。
表示①:”D:/wamp/img/a.txt”
表示②:”D:\wamp\img\a.txt”

3、文件的相对路径(重在理解)——英文的双引号
定义:目标文件相对于当前文件的路径。
表达形式:
(1)"./“或”.\”表示显示当前目录,也可以省略,表示默认当前目录
(2)”…/"或”…\”表示返回到上一级的目录。
(3)如果有多个上一级目录,可以使用多个“…/”或”…\”。

例2:”test.cpp”所在目录为”D:/wamp/”,而”a.txt”所在目录为 ”D:/wamp”。
那 么”a.txt”相对于”test.cpp”文件来说,是在其所在的当前目录里。因此,
”a.txt”文件的相对路径为:
”./a.txt” 或 ”.\a.txt” (显示当前目录)
”a.txt” (默认当前目录)

例3:”test.cpp”所在目录为”D:/wamp/www”,而”a.txt”所在目录为”D:/wamp”。
那 么”a.txt”相对于”test.cpp”文件来说,是在其所在目录的上级目录里。因此,
”a.txt”文件的相对路径为:”…/a.txt” 或 ”…\a.txt”

例4:”test.cpp”所在目录为”D:/wamp/www/file”,而”a.txt”所在目录为”D:/wamp”。
那 么”a.txt”相对于”test.cpp”文件来说,是在其所在目录的上级目录的上级目录里。因此,”a.txt”文件的相对路径为:”…/…/a.txt” 或 ”…\…\a.txt” (多个上级目录)

(三)文件的打开方式
ios::in 以输入方式打开文件,支持读数据流。如果文件不存在会找不到文件。
ios::out 以输出方式打开文件,支持写数据流。如果文件不存在则新建,
如果文件存在就清空其原有内容。
ios::app 输出的数据追加到文件末尾,只支持读,不支持写
ios::ate 打开一个文件,并将指针定位到文件末尾
ios::trunc 打开一个文件,如果文件不存在则新建,如果存在,则清空原有文件中的内容
ios::binary 以二进制方式打开文件,如果不指定则默认采用文本方式打开文件
说明:
①缺省时,默认为以输出和输入方式打开文件,支持读和写数据流。
②当以多种形式打开文件时,中间用运算符”|”(或)连接起来。如:

ios::in | ios::out 以输出和输入方式打开文件
ios::in | ios::binary 以输入方式打开一个二进制文件
ios::out| ios::binary 以输出方式打开一个二进制文件

(四)文件的属性
0——普通文件(支持读和写)
1——只读文件(只能读,不能写)
2——隐含文件
4——系统文件
说明:
①缺省时,默认为普通文件。
②对于文件的属性也可以使用“|”运算或“+”进行组合使用。

三、数据流对象指针(简称“流指针”)
1、定义流指针
对文件进行读写操作首先必须要定义一个数据流对象指针。
数据流对象指针有三种类型,它们分别是:
(1)Ifstream(头文件#include<ifstream>
表示文件读取流,对文件进行读操作,将数据从存储设备读取到内存中。
(2)ofstream(头文件#include<ofstream>
表示文件写入流,对文件进行写操作,将数据从内存写入存储设备中。
(3)fstream(头文件#include<fstream>
表示文件读取/写入流,对文件进行读和写操作,既可以将数据从存储设备读取到内存中,也可以将数据从内存写入存储设备中。

例5:ifstream f1; //定义读取流指针f1,只支持读操作
ofstream f2(“D:\a.txt”,ios::out); //定义指向a.txt文件的f2写入流指针,只支持写操作
fstream f3(“D:\a.txt”,ios::in|ios::out|ios::binary); //定义f3读取/写入流指针,支持读和写操作,以二进制形式打开文件

2、获取流指针的位置
(1)tellg( )
根据ANSI-C++ 标准,就是一个整数,代表当前读取流指针的位置;
(2)tellp( )
根据ANSI-C++ 标准,就是一个整数,代表当前写入流指针的位置;
例6: long long m=f1.tellg( );//返回f1的位置
long long m=f2.tellp( );//返回f2的位置

3、设置流指针的位置
(1)设置读取流指针的位置
①seekg ( pos_type position );
设置位置为指向从文件开始计算的一个绝对位置。
参数可以是具体的数值(数值的单位是字节)。
如:f1.seekg(12); //设置流指针的位置为文件开始计算12字节的位置
参数的取值也可以是:
ios::beg 设置流指针的位置为文件的开始,常用于重置流指针
ios::cur 设置流指针的位置为文件当前的位置
ios::end 设置流指针的位置为文件的末尾
如:f1.seekg(ios::beg);
②seekg ( off_type offset, seekdir direction );
设置位置为由参数direction决定的一个具体的指针开始计算的一个位移(offset)。
offset 是数值,数值的单位是字节。正的表示向后偏移,负的表示向前偏移。
参数direction的取值如下:
ios::beg 从流指针开始位置计算的位移
ios::cur 从流指针当前位置开始计算的位移
ios::end 从流指针末尾处开始计算的位移
如:f1.seekg(12,ios::beg);//从流指针开始位置向后偏移12个字节
F3.seekg(-12,ios::end);//从流指针末尾位置向前偏移12个字节

(2)设置写入流指针的位置
①seekp ( pos_type position );

设置位置为指向从文件开始计算的一个绝对位置。
参数可以是具体的数值(数值的单位是字节)。
如:f1.seekp(12); //设置流指针的位置为文件开始计算12字节的位置
参数的取值也可以是:
ios::beg 设置流指针的位置为文件的开始,常用于重置流指针
ios::cur 设置流指针的位置为文件当前的位置
ios::end 设置流指针的位置为文件的末尾
如:f1.seekp(ios::beg);
②seekp ( off_type offset, seekdir direction );
设置位置为由参数direction决定的一个具体的指针开始计算的一个位移(offset)。
offset 是数值,数值的单位是字节。正的表示向后偏移,负的表示向前偏移。
参数direction的取值如下:
ios::beg 从流开始位置计算的位移
ios::cur 从流指针当前位置开始计算的位移
ios::end 从流末尾处开始计算的位移
f2.seekp(12,ios::beg);//从流指针开始位置向后偏移12个字节
f3.seekp(-12,ios::end);//从流指针末尾位置向前偏移12个字节

四、文件的相关操作
1、文件的打开——open

ifstream类、ofstream类和fstream类都有一个成员函数open,实现文件的打开操作,将文件和数据流进行关联,通过数据流对象指针对文件进行读写操作。
函数有三个参数:打开的文件名、文件的打开方式、文件的属性。
(1)打开的文件名
①采用文件的绝对路径
如:”D:\in.txt” 或”D:/in.txt” (D盘下的in.txt文件)
②采用文件的相对路径
如:”./in.txt” 或”.\in.txt” (程序所在的当前目录中的in.txt文件)
如:”…/in.txt” 或”…\in.txt” (程序所在的目录的上级目录中的in.txt文件)

(2)文件的open函数的具体使用:
①定义一个数据指针流;(注:根据文件的操作类型选择对应的数据指针流类型)
②调用open函数;(注:参数写法的正确性)

例5:fstream f1,f2;//定义一个名为f1的数据流指针
         f1.open("D:\\a.txt"); //以读和写方式打开D盘中的a.txt文件
         F2.open(“../a.txt”.ios::in);//以读方式打开当前目录的上级目录中的a.txt文件

2、文件的关闭——close
(1)close函数的具体使用:

①定义一个数据指针流;(注:根据文件的操作类型选择对应的数据指针流类型)
②调用close函数;

例5:fstream f1;//定义一个名为f1的数据流指针
         f1.open("D:\\a.txt"); //以读和写方式打开D盘中的a.txt文件
         F1.close( );//关闭a文件

(2)close函数的相关说明:
①当文件读写操作完成之后,必须将文件关闭以使文件重新变为可访问的。
②close负责将缓存中的数据排放出来并关闭文件。这个函数一旦被调用,原先的流对象就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程所访问了。
③防止流对象被销毁时还联系着打开的文件。

由于类ofstream, ifstream 和fstream 是分别从ostream, istream 和iostream 中引申而来的,所以文本文件的读写操作与使用控制台函数cin和cout一样。而对于二进制文件,采用put和get(write 和 read)

3、文本文件的写操作——符号”<<”
(一)使用的方法
①定义一个数据指针流;(注:根据写操作选择对应的数据指针流类型)
②表达形式:数据指针流 << 被写入的对象;
例6:从键盘输入10个数字,并将这10个数写入D盘下的”a.txt”文件。

int  a[10];
fstream f1;//定义一个名为f1的数据流指针
    f1.open("D:\\a.txt"); //以读和写方式打开D盘中的a.txt文件
for (int i = 0; i < 10; i++) {
		cin >> a[i];
		f1 << a[i] << endl;  //将输入的数字依次写入文件中
	}
f1.close();//关闭文件

4、文本文件的读操作——符号”>>”
(一)使用的方法
①定义一个数据指针流;(注:根据读操作选择对应的数据指针流类型)
②表达形式:数据指针流 >> 读取后存储的对象;
注意:读取数据时按照文件中数据的格式读取。
例7:假设D盘下的”a.txt”文件中有10个数,将其全部读取出来,存储在数组b中。

int  b[10];
fstream f2;//定义一个名为f2的数据流指针
    f2.open("D:\\a.txt"); //以读和写方式打开D盘中的a.txt文件
for (int i = 0; i < 10; i++) {
		f1 >> b[i] ;  //读取时会根据文件中的格式读取。
	}
f2.close();//关闭文件

5、二进制文件的读和写操作
(1)二进制文件的读和写
①二进制文件的写操作——put

ofstream  f1(“a.txt”,ios::out);//定义一个名为f1的数据流指针
f1.put('c');   //往a.txt中写入字符c

②二进制文件的读操作——get

 ifstream  f2(“b.txt”,ios::in)
      f2.get(‘c’);  //从b.txt中读取字符c
      f2.get(str1,127,'A');//从文件中读取字符到字符串str1,当遇到字符'A'或读取了127个字符时终止。

(2)二进制数据块的读和写

read ( char * buffer, streamsize size );
write ( char * buffer, streamsize size );

其中buffer 是一块内存的地址,用来存储或读出数据。参数size 是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。

ifstream in (“a.txt”, ios::in|ios::binary|ios::ate); 
size1 = in.tellg(); 
char * buffer1 = new char [size1]; 
ofstream out(“b.txt”,ios::out);
size2 = out.tellp(); 
char * buffer2 = new char [size2]; 
in.read (buffer1, size1); 
out.write(buffer2,size2);

6、文件的其他函数操作
Is_open( ) 判断文件是否处于打开的状态。如果是,返回true;如果不是,返回false

eof() 判断读文件是否到达文件末尾。如果是,返回true;如果不是,返回false

bad() 如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间时,就会报错。

fail() 除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

good() 这是最通用的:如果调用以上任何一个函数返回true 的话,函数返回 false 。

clear() 重置以上成员函数所检查的状态标志。

特别说明:
当文件完成数据写入后,数据流指针就移动到文件的末尾;此时,若需要从文件中读取数据,则需要重置数据流指针,让指针移动到文件的开始。这是很多初学者遗落的知识点。

表达形式:数据流指针.seekg(ios::beg);
例8:在D盘中的”a.txt”文件写入10个数,并从文件中读取这10个数。

int  a[10],b[10];
fstream  f1;//定义一个名为f1的数据流指针
f1.open("D:\\a.txt"); //以读和写方式打开D盘中的a.txt文件
for (int i = 0; i < 10; i++) {
cin>>a[i];//从键盘中输入数字
		f1 << a[i]<<endl ;  //将数字写入文件,一个数字一行
	}
f1.seekg(ios::beg);  //重置数据流指针
for (int i = 0; i < 10; i++) {
		f1 >> b[i];//读入的时候会根据按照原来的格式读入。
		cout << b[i] << endl;  //在dos窗口中输出结果
	}
	f1.close(); //关闭文件

以上是文件的常见操作,希望学者认真学习,不要在程序中出现低级错误。
为了便于道友们向我咨询问题,特意开设了一个免费的知识星球——CaptianXue,星球提供学习、理财、生活、职场等各类文章和免费答疑!!
在这里插入图片描述

  • 87
    点赞
  • 428
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值