目录
一:目的
二:C语言文本文件读写
1. 文本文件写入
2. 文本文件读取
三:C语言二进制文件读写
1. 二进制文件写入
2.二进制文件读取
四:C++文本文件读写
1. 文本文件写入
2.文本文件读取
五:C++二进制文件读写
1. 二进制文件写入
2.二进制文件读取
六 总结
获取文件大小
方法一
方法二
一:目的
掌握C语言文本文件读写方式;
掌握C语言二进制文件读写方式;
掌握CPP文本文件读写方式;
掌握CPP二进制文件读写方式;
二:C语言文本文件读写
1. 写入文本文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| |
//采用C模式对Txt进行写出 void TxtWrite_Cmode() { //准备数据 int index[50] ; double x_pos[50], y_pos[50]; for(int i = 0; i < 50; i ++ ) { index[i] = i; x_pos[i] = rand()%1000 * 0.01 ; y_pos[i] = rand()%2000 * 0.01; } //写出txt FILE * fid = fopen("txt_out.txt","w"); if(fid == NULL) { printf("写出文件失败!\n"); return; } for(int i = 0; i < 50; i ++ ) { fprintf(fid,"d\t%4.6lf\t%4.6lf\n",index[i],x_pos[i],y_pos[i]); } fclose(fid); }
|
2. 读取文本文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| |
//采用C模式对Txt进行读取 void TxtRead_Cmode() { FILE * fid = fopen("txt_out.txt","r"); if(fid == NULL) { printf("打开%s失败","txt_out.txt"); return; } vector<<span style="color:#8000ff;">int> index; vector<<span style="color:#8000ff;">double> x_pos; vector<<span style="color:#8000ff;">double> y_pos; int mode = 1; printf("mode为1,按字符读入并输出;mode为2,按行读入输出;mode为3,知道数据格式,按行读入并输出\n"); scanf("%d",&mode); if(mode == 1) { //按字符读入并直接输出 char ch; //读取的字符,判断准则为ch不等于结束符EOF(end of file) while(EOF!=(ch= fgetc(fid))) printf("%c", ch); } else if(mode == 2) { char line[1024]; memset(line,0,1024); while(!feof(fid)) { fgets(line,1024,fid); printf("%s\n", line); //输出 } } else if(mode == 3) { //知道数据格式,按行读入并存储输出 int index_tmp; double x_tmp, y_tmp; while(!feof(fid)) { fscanf(fid,"%d%lf%lf\n",&index_tmp, &x_tmp, &y_tmp); index.push_back(index_tmp); x_pos.push_back(x_tmp); y_pos.push_back(y_tmp); } for(int i = 0; i < index.size(); i++) printf("d\t%4.8lf\t%4.8lf\n",index[i], x_pos[i], y_pos[i]); } fclose(fid); }
|
注意:上面的代码用while(!feof(fid)) 判断文件是否结束有一个问题,就是如果文件是空文件,第一次循环会进去。
feof(fp) 就是判断fp是否已经读取了EOF字符。如果已读取,返回true值,所以在调用feof(fp) 之前,都应该先调用读文件的函数: fgets(ar, 50,fid)、fgetc(fid),然后再判断就OK。
正确使用feof():
#include<stdio.h>
int main(void)
{
FILE *p;
p = fopen("open.txt", "r");
getc(p);
if (feof(p))
{
printf("文件为空。");
}
else
{
rewind(p);
int a;
fscanf(p,"%d",&a);
printf("%d", a);
}
return 0;
}
————————
三:C语言二进制文件读写
1. 写入二进制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| |
//采用C模式写二进制文件 void DataWrite_CMode() { //准备数据 double pos[200]; for(int i = 0; i < 200; i ++ ) pos[i] = i ; //写出数据 FILE *fid; fid = fopen("binary.dat","wb"); if(fid == NULL) { printf("写出文件出错"); return; } int mode = 1; printf("mode为1,逐个写入;mode为2,逐行写入\n"); scanf("%d",&mode); if(1==mode) { for(int i = 0; i < 200; i++) fwrite(&pos[i],sizeof(double),1,fid); } else if(2 == mode) { fwrite(pos, sizeof(double), 200, fid); } fclose(fid); }
|
---------
2.读取二进制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| |
//采用C模式读二进制文件 void DataRead_CMode() { FILE *fid; fid = fopen("binary.dat","rb"); if(fid == NULL) { printf("读取文件出错"); return; } int mode = 1; printf("mode为1,知道pos有多少个;mode为2,不知道pos有多少个\n"); scanf("%d",&mode); if(1 == mode) { double pos[200]; fread(pos,sizeof(double),200,fid); for(int i = 0; i < 200; i++) printf("%lf\n", pos[i]); free(pos); } else if(2 == mode) { //获取文件大小 fseek (fid , 0 , SEEK_END); long lSize = ftell (fid); rewind (fid); //开辟存储空间 int num = lSize/sizeof(double); double *pos = (double*) malloc (sizeof(double)*num); if (pos == NULL) { printf("开辟空间出错"); return; } fread(pos,sizeof(double),num,fid); for(int i = 0; i < num; i++) printf("%lf\n", pos[i]); free(pos); //释放内存 } fclose(fid); }
|
——————
四:C++文本文件读写
1. 写入文本文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| |
//采用CPP模式写txt #include <fstream> void TxtWrite_CPPmode() { //准备数据 int index[50] ; double x_pos[50], y_pos[50]; for(int i = 0; i < 50; i ++ ) { index[i] = i; x_pos[i] = rand()%1000 * 0.01 ; y_pos[i] = rand()%2000 * 0.01; } //写出txt fstream f("txt_out.txt", ios::out); if(f.bad()) //判断文件打开是否成功,使用is_open()接口,不能使用bad()接口,bad()接口是用来判断读写是否有错。 { cout << "打开文件出错" << endl; return; } for(int i = 0; i < 50; i++) f << setw(5) << index[i] << "\t" << setw(10) << x_pos[i] <<"\t" <<setw(10)<< y_pos[i] << endl; f.close(); }
|
-----
2.读取文本文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| |
/采用CPP模式读取txt #include <fstream> void TextRead_CPPmode() { fstream f; f.open("txt_out.txt",ios::in); //文件打开方式选项: // ios::in = 0x01, //供读,文件不存在则创建(ifstream默认的打开方式) // ios::out = 0x02, //供写,文件不存在则创建,若文件已存在则清空原内容(ofstream默认的打开方式) // ios::ate = 0x04, //文件打开时,指针在文件最后。可改变指针的位置,常和in、out联合使用 // ios::app = 0x08, //供写,文件不存在则创建,若文件已存在则在原文件内容后写入新的内容,指针位置总在最后 // ios::trunc = 0x10, //在读写前先将文件长度截断为0(默认) // ios::nocreate = 0x20, //文件不存在时产生错误,常和in或app联合使用 // ios::noreplace = 0x40, //文件存在时产生错误,常和out联合使用 // ios::binary = 0x80 //二进制格式文件 vector<<span style="color:#8000ff;">int> index; vector<<span style="color:#8000ff;">double> x_pos; vector<<span style="color:#8000ff;">double> y_pos; if(!f) { cout << "打开文件出错" << endl; return; } cout<<"mode为1,按字符读入并输出;mode为2,按行读入输出;mode为3,知道数据格式,按行读入并输出"<<endl; int mode = 1; cin>>mode; if(1== mode) { //按字节读入并输出 char ch; while(EOF != (ch= f.get())) cout << ch; } else if(2 == mode) { //按行读取,并显示 char line[128]; int numBytes; f.getline(line,128); cout << line << "\t" << endl ; f.getline(line,128); cout << line << "\t" << endl ; f.seekg(0,0); //跳过字节 //seekg(绝对位置); //绝对移动, //输入流操作 //seekg(相对位置,参照位置); //相对操作 //tellg(); //返回当前指针位置 while(!f.eof()) { //使用eof()函数检测文件是否读结束 f.getline(line,128); numBytes = f.gcount(); //使用gcount()获得实际读取的字节数 cout << line << "\t" << numBytes << "字节" << endl ; } } else if(3 == mode) { //如果知道数据格式,可以直接用>>读入 int index_temp = 0; double x_pos_temp = 0, y_pos_temp = 0; while(!f.eof()) { f >> index_temp >> x_pos_temp >> y_pos_temp ; index.push_back(index_temp); x_pos.push_back(x_pos_temp); y_pos.push_back(y_pos_temp); cout << index_temp << "\t" << x_pos_temp << "\t" << y_pos_temp << endl; } } f.close(); }
|
--
五:C++二进制文件读写
1. 写入二进制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| |
/采用CPP模式写二进制文件 #include <fstream> void DataWrite_CPPMode() { //准备数据 double pos[200]; for(int i = 0; i < 200; i ++ ) pos[i] = i ; //写出数据 ofstream f("binary.dat",ios::binary); if(!f) { cout << "创建文件失败" <<endl; return; } f.write((char*)pos, 200*sizeof(double)); //fwrite以char *的方式进行写出,做一个转化 f.close(); }
|
--
2.读取二进制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| |
//采用CPP模式读二进制文件 #include <fstream> void DataRead_CPPMode() { double pos[200]; ifstream f("binary.dat", ios::binary); if(!f) { cout << "读取文件失败" <<endl; return; } f.read((char*)pos,200*sizeof(double)); for(int i = 0; i < 200; i++) cout << pos[i] <<endl; f.close(); }
|
--
六 总结
1. C语言读写文件均通过FILE指针执行操作,其中文本文件的读写用fprintf,fscanf,二进制文件的读写用fread,fwrite
2. C++读写文件通过fstream、ifstream、ofstream进行操作,文本文件用<< 和 >> 进行读写,二进制文件用read和write进行读写
获取文件大小
获取文件大小这里有两种方法:
方法一
范例:
unsigned long get_file_size(const char *path)
{
unsigned long filesize = -1;
FILE *fp;
fp = fopen(path, "r");
if(fp == NULL)
return filesize;
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
fclose(fp);
return filesize;
}
此种以打开文件的方法取得文件的大小,不适合大文件,并且可能会出现访问冲突(比如正在下载的文件),效率也比较低
方法二
范例:
-
- #include <sys/stat.h>
-
- unsigned long get_file_size(const char *path)
- {
- unsigned long filesize = -1;
- struct stat statbuff;
- if(stat(path, &statbuff) < 0){
- return filesize;
- }else{
- filesize = statbuff.st_size;
- }
- return filesize;
- }
-
此种使用读取文件属性的方法得到文件的大小,效率较高,也较稳定
用fstream读写文件容易犯的错系统学习Windows客户端开发
fstream属于C++标准,使用fstream进行文件读写,具有跨平台性。使用过程中要注意几点:
第一,构造函数中指定文件路径时内部会调用open(),如果再次调用open(),调用将会返回失败。
第二,判断文件打开是否成功,使用is_open()接口,不能使用bad()接口,bad()接口是用来判断读写是否有错。
第三,如果文件内容有包含\0,open()时指定fstream::binary标志位进行二进制流的读写。如果写文件希望追加不清除原有内容,open()时指定fstream::app标志位(append的缩写)。
第四,为了计算文件大小,需要先将位置指向结尾,这时要调seekg(0, ios_base::end),而不是seekg(ios_base::end),seekg有两个重载函数,只带一个参数的接口表示相对开始的位置,ios_base::end的值为2,seekg(ios_base::end)表示移到2的位置,而不是文件末尾。
第五,慎用操作符>>和<<读写文件,操作符>>和<<类似于scanf()接口,它是基于字符串格式化输入输出,比如unsigned short x=200, y=300; ofs <<x<<y;文件内容是字符串200300,而不是数值c8002c01,因为操作符<<会先将数值转化为字符串再写入文件。ifs>>x>>y;操作符>>读取x和y时,首先获得字符串200300,再赋值给x,因为x是unsigned short类型最大值为65535,200300超过65535,读取失败。所以某些场景下用操作符<<和>>进行文件读写是不可逆,应该用read(), write()接口读写。
下面代码详细演示fstream的使用及要注意的地方。
#include <string>
#include <fstream>
using namespace std;
#pragma pack(1)
struct CPoint
{
public:
char m_cType = 0;
unsigned short m_nX = 0;
unsigned short m_nY = 0;
};
#pragma pack()
int main()
{
const std::wstring strFilePath = L"C:\\test.dat";
CPoint pt;
pt.m_cType = 0;
pt.m_nX = 200;
pt.m_nY = 300;
ofstream ofs(strFilePath.c_str(), fstream::out | fstream::binary);
if (ofs.is_open())
{
ofs << pt.m_cType << pt.m_nX << pt.m_nY;
ofs.close();
}
ifstream ifs(strFilePath.c_str(), fstream::in | fstream::binary);
if (ifs.is_open())
{
CPoint pt2;
ifs >> pt2.m_cType >> pt2.m_nX >> pt2.m_nY;
printf("x= %d, y = %d\n", pt2.m_nX, pt2.m_nY);
ifs.close();
}
ofstream ofs2(strFilePath.c_str(), fstream::out | fstream::binary);
if (ofs2.is_open())
{
ofs2.write((const char*)&pt, sizeof(pt));
ofs2.close();
}
ifstream ifs2(strFilePath.c_str(), fstream::in | fstream::binary);
if (ifs2.is_open())
{
CPoint pt2;
ifs2.read((char*)&pt2, sizeof(pt2));
printf("x= %d, y = %d\n", pt2.m_nX, pt2.m_nY);
ifs2.close();
}
return 0;
}