【C++】fstream文件操作
C语言使用FILE对文件进行操作,常用到的函数有fopen()、freopen()、fread()、fwrite()、fclose()等,分别用来打开文件、读写文件、关闭文件。
C++可以使用fstream文件流对文件进行操作,使用时需要引入头文件:#include <fstream>。可以使用ifstream、ofstream、fstream文件流对文件进行输入(读)、输出(写)、输入输出(读写)操作。Ifstream支持>>操作,ofstream支持<<操作,fstream同时支持>>和<<操作。
本文简单介绍C++文件流的操作:
目录
一、打开、关闭文件
- 打开文件 fstream可以在声明流对象时传入文件名打开文件,也可以使用open()函数打开文件。
- 关闭文件 文件打开后必须关闭,fstream提供close()函数关闭文件。
打开文件
- 使用构造函数声明对象时打开文件,示例:
fstream file(filename, ios::in | ios::out);
- 使用open()函数打开文件,函数原型:
void open(const char* filename,int mode,int access); // filename—文件名;mode—打开文件的模式;access—文件属性
如果只传入文件名,系统会自动根据文件类型选择默认的打开模式。
打开文件模式mode及文件属性access取值如下:
mode | 打开文件模式 | 说明 |
access |
文件属性 | 说明 |
ios::app | 以追加的方式打开文件 | 0 | 普通文件,打开访问 | ||
ios::ate | 文件打开后定位到文件尾,ios::app包含此属性 | ||||
ios::binary | 以二进制方式打开文件,默认是文本文件 | 1 | 只读文件 | ||
ios::in | 以输入方式打开,读出文件内容 | ||||
ios::out | 以输出方式打开,写入文件内容 | 2 | 隐含文件 | ||
ios::nocreate | 以不创建文件的方式打开文件,如果文件不存在,打开失败 | ||||
ios::noreplace | 以不覆盖的方式打开文件,如果文件存在,打开失败 | 4 | 系统文件 | ||
ios::trunc | 如果文件存在,清空文件内容 |
说明:
- 模式和属性可以单独使用给,也可以混合使用。混合使用时,用逻辑连接符或 |连接。
- ios::out模式默认会清空,即iios::out|ios::trunc和ios::out打开文件时都会清空文件。如果不想清空文件,那么设置读写模式为ios::out|ios::app,以这种模式打开文件后,数据会以追加的方式写入到文件。
二、 读写文件
fstream提供的读写操作有:<<、>>、read()、write()、put()、get()、getline()。根据文件类型可分为文本文件和二进制文件,根据读写方式可分为逐行读写和整块读写。通常,文本文件使用逐行读写的方式,二进制文件使用整块读写的方式。
1. 文本文件读写
文本文件通常使用逐行读写的方式。逐行读取文本文件时可以使用getline()函数。系统库和fstream都提供了同名的getline()函数,不同点在于fstream文件流提供的getline()函数是C语言格式的,而系统库提供的getline()函数是C++格式的,如下:
fstream提供的getline()函数 |
系统库提供的getline()函数 |
ifstream in(“test.txt”); char temp[1024]’ while(!in.eof()) { in.getline(temp,1024); } |
ifstream in(text.txt); std::string strline; while(!in.eof()) { getline(in,strline); } |
逐行写入文本文件可以使用操作符<<。
2. 二进制文件的读写
二进制文件通常整块读取或写入,当然也可以读写单个字符,用到的函数包括:put()、get()、read()、write()。
通常使用write()、put()函数写入二进制文件。使用read()、get()读取二进制文件。
- 读写数据块
使用read()和write()函数读写数据块,原型如下:
istream& read(char* buffer,int count); ofstream& write(char* buffer,int count); //从buf指向的缓存向文件写入count个字符。
需要注意的是:read()函数从文件中读取count个字符,读取到buffer指向的缓存中,如果还未读入num个字符就到了文件尾,可以用成员函数gcount()获取实际读取的字符数。
- 读写单个字符
通常使用get()、put()函数读写单个字符
put()函数向文件写入一个字符,原型为ofstream& put(char ch);
get()函数从文件读取一个字符,有三种重载形式:
① ifstream& get(char& ch); 从流中读取一个字符,如果到文件尾,返回空字符。
② int get(); 从流中返回一个字符,如果到达文件尾,返回EOF,
③ ifstream& get(char* buf,int count,char delim=”\n; 把字符读入buf指向的缓存中,知道读入了count个字符或者遇到delim指定的字符。
三、 定位文件指针、获取文件大小
C++的文件定位分为读位置和写位置的定位,对应的成员函数分别为seekg()和seekp()。
seekg()函数设置读位置,seekp()设置写位置。函数原型如下:
istream& seekg(streamoff offset,seek_dir origin);
ofstream& seekp(streamoff offset,seek_dir origin);
offset表示偏移量,seek_dir表示移动的基准位置,取值如下:
ios::beg 文件开头
ios::cur 文件当前位置
ios::end 文件结尾
示例:
inFile.seekg(12,ios::beg); // 把文件读指针从开始位置向后移动12个字节 outFile.seekp(12,ios::cur); // 把文件写指针从当前位置向后移动12个字节
获取文件大小可以使用seekg()和tellg()或者seekp()和tellp()函数结合使用的方式获取文件大小。
示例:
inFile.seekg(0,ios::end); // 读文件指针移动到文件末尾 streampos ipos = inFile.tellg(); //返回当前指针的位置,也就是文件的大小,单位是字节
四、 示例代码
//读写txt文件 std::string in_read_txt = "in_read.txt"; std::ifstream file_in_read_txt(in_read_txt); // 读取文件 // 文本文件逐行读取数据 if(!file_in_read_txt.is_open()) // 判断文件是否打开 { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } std::string strline; std::vector<std::string> vecLine; while (getline(file_in_read_txt,strline)) { // 逐行获取txt内容 std::cout << strline << std::endl; vecLine.push_back(strline); } file_in_read_txt.close(); // 文本文件逐行写入 std::string out_write_txt = "out_write.txt"; std::ofstream file_out_write_txt(out_write_txt,std::ios::trunc); // 写入txt文件 if(!file_out_write_txt.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } for(std::string& line : vecLine) { file_out_write_txt << line << std::endl; //逐行写入文件 } file_out_write_txt.close(); std::string in_read_bin = "in_read.bin"; std::string out_write_bin = "out_write.bin"; std::ifstream file_in_read_bin(in_read_bin,std::ios::binary); // 以二进制方式读取文件 std::ofstream file_out_write_bin(out_write_bin,std::ios::binary); // 以二进制方式写入文件 // 二进制文件获取数据 if(!file_in_read_bin.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } uchar binData[2048] = {0}; file_in_read_bin.read((char*)binData,sizeof(binData)); int iDataSize = file_in_read_bin.gcount(); printf("Read Data Size = %d\n",iDataSize); for(int i=0;i<iDataSize;i++) { printf("0x%04x,0x%02x\n",i,binData[i]); } //使用get()函数获取文件内容 // char chTemp; // 第一种用法 // while (file_in_read_bin.get(chTemp)) { // printf("0x%02x\n",(uchar)chTemp); // } // 第二种用法 // for(int i=0;i<1372;i++) // { // chTemp = file_in_read_bin.get(); // printf("0x%02x\n",(uchar)chTemp); // } // 第三种用法 // file_in_read_bin.get((char*)binData,sizeof(binData)); // for(int i=0;i<sizeof(binData);i++) // { // printf("0x%04x,0x%02x\n",i,binData[i]); // } file_in_read_bin.close(); // 写入bin文件 if(!file_out_write_bin.is_open()) { std::string sErrmsg = "Open File FAIL"; throw sErrmsg; } file_out_write_bin.write((char*)binData,iDataSize); file_out_write_bin.close();