常用的C/C++文本文件的读写函数

一. 概述

文本文件的读写是算法研究和工程应用中常见的功能模块。C和C++的标准库中提供了多种文本文件的读写方法,我们一般都会掌握其中比较习惯使用的一种或几种方法。解决问题的方法不在多,而在精。经过在网上的资料搜索和总结,这里我对实际编程中经常用到的几类方法总结如下。对C和C++分开介绍,目的是让大家即能用C++读写文本文件,又能用C读写文本文件。不多不少,恰到好处地掌握好该掌握的读写知识。
文本文件内容:后面在代码示例中读入的文本文件text.txt的内容如下:

Never give up, it's truth.
012  34 

二. C读写函数

这里我们使用简捷好用的流式文件操作,即FILE结构,需要加入头文件fstream.h。可以通过FILE *fopen(const char *filename,const char *mode)打开文件流。其中,参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下:

  • r 以只读方式打开文件
  • rb 以只读方式打开二进制文件
  • a 以追加(写)方式打开文件
  • w 以只写方式打开文件
  • wb 以只写方式打开二进制文件
  • r+ 以读/写方式打开文件,如无文件出错
  • w+ 以读/写方式打开文件,如无文件生成新文件

下面通过特别设置的实例对相应的函数进行介绍和说明。

1. 文本文件

读操作

函数fscanf的格式控制非常方便,基本上能应对所有的文本文件读取任务。有时候为了更便捷,需要使用某些特定功能的函数:
int fseek(FILE *stream, long offset, int whence)
此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置。参数offset是移动的字符数,whence是移动的基准可取值为:SEEK_SET 0 文件开头;SEEK_CUR 1 当前读写的位置;SEEK_END 2 文件尾部。
char *fgets(char *s, int n, FILE *stream)
此函数表示从流中读一行或指定个字符(n-1),参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。

string filePath = "text.txt";
FILE *fp = fopen(filePath.c_str(), "r");
if (fp == nullptr)
{
    cout<<"Invalid file path\n";
    return;
}
char str[512];
fscanf(fp, "%s", &str);
int offset = sizeof(char)*9;
fseek(fp, offset, 1);
char str1[512];
int n = 12;
fgets(str1, n+1, fp);
cout<<str1<<endl;
int no, k1, k2;
fscanf(fp, "%d%s%d%d", &no, &str, &k1, &k2);
cout<<no<<" "<<k1<<" "<<k2<<endl; 
写操作

函数fprintf主要要掌握的就是对于输出格式的控制,语法规则是百分符号%+代表类型的字母,格式控制就写在二者之间。

  • %d 整数int型
  • %f 单精度float型
  • %lf 双进度double型
  • %e 以科学计数法表示
  • %s 字符串char[]型

下列代码中,%6.2lf表示以6个字符宽度、2位小数的精度输出;%03d表示以3个字符宽度不足部分以0填充的格式输出。

string filePath = "text.txt";
FILE *fp = fopen(filePath.c_str(), "a");
if (fp == nullptr)
{
    cout<<"Invalid file path\n";
    return;
}
int a = 91;
fprintf(fp, "C appending %03d\n", a);
double k = 192.3345;
fprintf(fp, "%6.2lf\n", k);
fclose(fp);

2. 二进制文件

相比文本文件而言,二进制文件的读写不需要考虑输出格式的相关问题。原因有二,一是二进制文件内容是用户看不懂的二进制字节;二是二进制文件的读写操作都是按字节个数读取的,无需顾及格式。所以,写二进制文件的时候千万不要输出那些格式控制相关的字符,如\n,那样徒增数据读取的难度,百害而无一益。

读操作

函数fread的原型是size_t fread(void ptr, size_t size, size_t n, FILE *stream),参数ptr是保存读取的数据,void的指针可用任何类型的指针来替换,如char*、int *等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数)。

string filePath = "binary.bin";
FILE *fp = fopen(filePath.c_str(), "rb");
int intSize = sizeof(int);
int charSize = sizeof(char);
char *buffer1 = new char[13];
int *buffer2 = new int[3];
fread(buffer1, charSize, 13, fp);
fread(buffer2, intSize, 3, fp);
cout<<buffer1<<endl;
cout<<buffer2[0]<<" "<<buffer2[1]<<" "<<buffer2[2]<<endl;
fclose(fp);
写操作

函数fwrite的形参类型与上文提到的函数fread的形参类型一致,此处不再赘述。

string filePath = "binary.bin";
FILE *fp = fopen(filePath.c_str(), "wb");
int intSize = sizeof(int);
int charSize = sizeof(char);
int doubleSize = sizeof(double);
char *buffer1 = "Hello, world!";
int *buffer2 = new int[3];
buffer2[0] = 0; buffer2[1] = 12; buffer2[2] = 34;
double *buffer3 = new double[1];
buffer3[0] = 192.3;
fwrite(buffer1, charSize,  13, fp);
fwrite(buffer2, intSize,    3, fp);
fwrite(buffer3, doubleSize, 1, fp);
fclose(fp);

三. C++读写函数

在C++中,对文件的操作是通过stream的子类fstream来实现的。要用这种方式操作文件,就必须加入头文件fstream.h。。

1. 文本文件

读操作

函数open的原型是*void open(const char filename,int mode,int access)。参数filename:要打开的文件名;参数mode:要打开文件的方式;access:打开文件的属性。打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下(可以用“|”或者“+”把以下属性连接起来):

  • ios::in 以只读方式打开文件
  • ios::out 以只写方式打开文件
  • ios::app 以追加(写)方式打开文件
  • ios::_Nocreate 不建立文件,所以文件不存在时打开失败
  • ios::_Noreplace 不覆盖文件,所以打开文件时如果文件存在失败
  • ios::binary 以二进制方式打开文件

另外,此处代码中的函数seekggetline的用法和功能与C读写函数中的fseekfgets类似,故略之。

string filePath = "text.txt";
ifstream fin;
fin.open(filePath.c_str(), ios::in);
char str[512];
fin>>str;
int offset = 9;
fin.seekg(offset, ios::cur);
int n = 12;
char str1[512];
fin.getline(str1, n+1);
cout<<str1<<endl;
int no, k1, k2;
fin>>no;
int n = 2;  //! to skip ':' and ' '
fin.seekg(n+1, ios::cur);
fin>>k1>>k2;
cout<<no<<" "<<k1<<" "<<k2<<endl;
fin.close();
写操作

在C++语法中,文本文件输出函数的重点也是对输出格式的控制。这里是通过调用标准库中相应的输出格式设置函数来实现的,调用时需要包含头文件iomanip.h。比较常用的格式控制函数有:字符宽度设置函数setw;默认填充字符设置函数setfill;输出精度设置函数setprecision。具体的用法如下列代码中的调用方法。

string filePath = "text.txt";
ofstream fout;
fout.open(filePath.c_str(), ios::app | ios::_Nocreate);
char str[512] = "C++ appending ";
fout<<str;
fout<<0<<" : "<<oct<<12<<" "<<dec<<34<<endl;
fout<<setw(3)<<setfill('0')<<91<<" ";
double k = 192.9773;
fout<<setprecision(6)<<k<<endl;
fout.close();

2. 二进制文件

在C++中,对二进制的读写是通过函数readwrite来实现。这组函数的用法和功能与C中的函数freadfwrite相一致,这里不再做过多介绍。值得注意的是,函数的第一个形参类型必须是 unsigned char *,因此当数据的真实类型不是unsigned char时,需要进行类型转换。

读操作
string filePath = "binary.bin";
ifstream fin;
fin.open(filePath.c_str(), ios::binary);
int intSize = sizeof(int);
int charSize = sizeof(char);
char *buffer1 = new char[13];
char *buffer2 = new char[3*intSize];
fin.read(buffer1, charSize*13);
fin.read(buffer2, intSize*3);
cout<<buffer1<<endl;
cout<<(int)buffer2[0]<<" "<<(int)buffer2[1]<<endl;
fin.close();
写操作
string filePath = "binary.bin";
ofstream fout;
fout.open(filePath.c_str(), ios::binary);
int intSize = sizeof(int);
int charSize = sizeof(char);
int doubleSize = sizeof(double);
char *buffer1 = "Hello, world!";
char *buffer2 = new char[3*intSize];
buffer2[0] = 0; buffer2[1] = 12; buffer2[2] = 34;
char *buffer3 = new char[doubleSize*1];
buffer3[0] = 192.3;
fout.write(buffer1, charSize*13);
fout.write(buffer2, intSize*3);
fout.write(buffer3, doubleSize*1);
fout.close();

四. 总结

本文总结了C和C++中常用的读写文本文件和二进制文件的函数。目的是为C/C++初学者提供一份简单实用、详略得当的关于文件读写的学习资料。当然,要真正掌握其用法,还必须是亲身实践和多次练习,实践出真知!

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值