文件读写的步骤:
1、包含的头文件:#include <fstream>//使用文件流进行操作
2、创建流
3、打开文件(文件和流关联)
4、读写 (写操作:<<,put( ), write( ) 读操作: >> , get( ),getline( ), read( ))
5、关闭文件:把缓冲区数据完整地写入文件, 添加文件结束标志, 切断流对象和外部文件的连接
---------------------------
文件的读写:
1、文本文件的读写:
方法:
一次性读写若干字符
1)使用运算符<< 和 >>进行读写
功能:
<< 能实现以行为单位写入文件
>> 不能一行为单位读入内存,总是以空格、Tab、回车结束,而是以单词为单位
//函数功能:使用<< ,写入文件一行字符
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ofstream OpenFile("file.txt");//file.txt不需要提前建立存在,执行程序时发现没有此文件会
//自己创建if (OpenFile.fail()){cout << "打开文件错误!" << endl;exit(0);}OpenFile << "abc def ghi";OpenFile.close();system("pause");
}
程序执行结果:文件中写入内容:abc def ghi
//函数功能:使用>>,从文件读入一个单词
#include <fstream>
#include <iostream>
using namespace std;
void main()
{const int len = 20;char str[len];ifstream OpenFile("file.txt");//必须是实现建立好已经存在的文件,否则打开文件错误if (OpenFile.fail()){cout << "打开文件错误!" << endl;exit(0);}OpenFile >> str; //此处并不是让你输入,而是从文件中读取cout << str << endl;OpenFile.close();system("pause");
}
运行结果:str的内容为abc,而不是abc def ghi(见空格停止)
如果file.txt该文本中为空,则执行程序的结果为左图(表明文中第15行并不是类似于cin的从键盘输入操作,而此处是从文件中读取)。 如果file.txt该文本中是第一个程序执行后的结果,该程序执行结果如右图。
2)使用运算符<<(写)和getline()进行读写
功能:
<<:以行为单位输入文件
getline():以行为单位 读入内存,能一次读入一行
函数原型:istream &getline( char *buffer, streamsize num );
功能:getline( )函数用于从文件读取num-1个字符到buffer(内存)中,直到下列情况发生时,读取结束:
1):num - 1个字符已经读入
2):碰到一个换行标志
3):碰到一个EOF
/*getline()的原型是istream& getline ( istream &is , string &str , char delim );会生成一个包含一串从输入流读入的字符的字符串,
直到以下情况发生会导致生成的此字符串结束:1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度。
getline(<字符数组chs>,<读取字符的个数n>,<终止符>)*/
//使用运算符<<(写)和getline()进行读写
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ const int len=20; char str[len]; ifstream OpenFile("file.txt"); if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } OpenFile.getline(str,20); cout<<str<<endl; OpenFile.close(); system("pause");
}
运行结果:str的内容为abc def ghi (一直把一行读完)
------使用读取整行文本的函数。全局函数 getline() 可以用于此目的,它也是字符串库的一部分。其用法如下。
istream& getline (istream& is, string& str, char delim = '\n');
该函数从流 is 中读取一行文本,并将其存储到字符串变量 str 中。该函数具有一个可选的形参 delim,用于标记要读取的行的结尾。分隔字符被从流中移除并丢弃。如果在没有第 3 个形参的情况下调用 getline,则分隔符被认为是行尾字符 '\n'。
第一个参数 is,必须是 istream 类的一个对象。它也可以是 istringstream、ifstream 或 fstream 类中的任何对象(如果传递了 fstream 对象,则必须打开它才能输入)。返回的值是对刚刚读取的输入流的引用。这允许测试返回值以确定调用的成功或失败,如下面的代码段所示:
string str;
if (getline(inputstream, str))
{//读取一行并存储到str中cout << str << endl;
}
else
{//出现错误或到达文件末尾
}
或者,也可以忽略返回值并在调用后的语句中测试流:
string str;
getline(inputstream, str);
if (inputstream)
{//读取一行并存储到str中cout << str << endl;
}
else
{//出现错误或到达文件末尾
}
使用 getline 函数逐行读取文件,从而保留了单词之间的白色空格:
// This program uses the getline function to read a line of information from the file.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{// Variables needed for file inputfstream nameFile;string input;// Open the filenameFile. open ("murphy.txt" , ios::in);if (!nameFile){cout << "File open error!" << endl;return 0;}// Read first line of the filegetline(nameFile, input);//该函数从流 nameFile 中读取一行文本,并将其存储到字符串变量 input 中while (nameFile){//If successful, print line and read another linecout << input << endl;getline(nameFile, input);}// Close the filenameFile.close();return 0;
}
提前建立的murphy.txt文档内容如左边; 程序执行结果如右边。
由于 getline 函数的第 3 个参数在此程序中被省略了,所以它的默认值是 \n。有时可能想要指定另一个分隔符。例如,来看一个包含多个名称和地址的文件,比如存在一个addresses.txt,其内部格式如下:
可以将该文件看成是由 3 个记录组成的。记录是关于单个项目的完整信息集。另外,文件中的记录由 3 个字段组成:
- 第一个字段就是某人的名字;
- 第二个字段是某人的街道地址或邮政信箱号码;
- 第三个字段包含某人的城市、州和邮政编码。
PS:请注意,每个字段以 $ 字符结尾,每个记录以 \n 字符结尾。下面的程序演示了如何使用 getline 函数来检测 $ 字符:
// This file demonstrates the getline function with a user-specified delimiter.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;int main()
{// Variable needed to read filestring input;// Open the file.fstream dataFile ("addresses.txt", ios::in);if (!dataFile){cout << "Error opening file.";return 0;}// Read lines terminated by '$'' sign and outputgetline(dataFile, input, '$');//$用于标记要读取的行的结尾while (!dataFile.fail()) //判断是否存在有效的输入流{cout << input << endl; //输出检测到的第一个$之前的内容 并进行换行getline(dataFile, input, '$');//再次调用getline函数}// Close the filedataFile.close ();return 0;
}
此程序输出结果为:
请注意,标记每个记录结尾的 \n 字符也是输出的一部分。它们会在屏幕上打印出额外的空白行,将记录分开。
另外,使用 $ 之类的可打印字符分隔文件中的信息时,请务必选择一个实际上不会出现在信息本身中的字符。由于任何人的姓名或地址含有 $ 字符都是值得怀疑的,所以在这里它是一个可接受的分隔符。但如果文件中包含美元金额,则应该选择另一个分隔符。
while(getline())见链接:
https://mp.csdn.net/console/editor/html/104759846
一次读写一个字符:
使用get( )和put( )函数
函数声明:istream& get(char &c);
//使用 get( )函数 把字符1输入到文件
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch='1'; ofstream OpenFile("file.txt"); //该file.txt文档不需要提前建立,检测到没有此文件会自动创建if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } OpenFile.put(ch); OpenFile.close(); system("pause");
}
运行结果:把字符1写入文件
//函数功能:使用 put( )函数 把文件中第一个字符输入内存
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch; ifstream OpenFile("file.txt"); //需要提前存在file.txtif (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } OpenFile.get(ch); cout<<ch; OpenFile.close(); system("pause");
}
运行结果:把字符1从文件中读到ch(内存)中
第15行不加<<endl输出结果为左图。 加入输出结果如右图。 PS:就是一个换行的功能
2、二进制文件的读写:
1)使用运算符get( ) 和 put( )读写一个字节
功能:
get( ) :在文件中读取一个字节到内存
函数原型:ifstream &get(char ch)
put( ) :在内存中写入一个字节到文件
函数原型:ofstream &put(char ch)
//功能:把26个字符写入文件中
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch='a'; ofstream OpenFile("file.txt",ios::binary); //file.txt此文档无需提前建立好,检测到不存在会自动进行创建if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } for (int i=0;i<26;i++) { OpenFile.put(ch); ch++; } OpenFile.close(); system("pause");
}
运行结果:文件内容为abcdefghijklmnopqlst...z
//功能:把文件中的26个字母读入内存
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch; ifstream OpenFile("file.txt",ios::binary); //file.txt需要提前建立存在 ,否则打开文件错误if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } while (OpenFile.get(ch)) cout<<ch; OpenFile.close(); system("pause");
}
运行结果:ch依次为abc...z PS:加入换行符<<endl的不同输出结果。
2)使用read()和write()进行读写
read( ):
功能:从文件中提取 n 个字节数据,写入buf指向的地方中
函数声明:istream & read ( char * buf , int n ) ;
write( ):
功能:把buf指向的内容取n个字节写入文件
函数声明:ostream & ostream :: write ( char * buf , int n ) ;
参数说明:buf表示要写入内存的地址,传参时要取地址。n表示要读入字节的长度
注意:1):该函数遇到空字符时并不停止,因而能够写入完整的类结构
2):第一个参数一个char型指针(指向内存数据的起始地址),与对象结合使用的时候,要在对象地址之前要char做强制类型转换。
//函数功能:使用write( )函数,一次从内存向文件写入一行数据
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch[12]="12 3 456 78"; ofstream OpenFile("file.txt"); //不需要提前建立file.txt文件,检测到不存在会自动建立,如果提前存在,会覆盖掉原来的file.txt重新建立一个。if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } OpenFile.write(ch,12); OpenFile.close(); system("pause");
}
运行结果:文件内容12 3 456 78
将OpenFile.write(ch,12)改变参数为OpenFile.write(ch,8),程序执行结果如右图只读取8个字节长度。
//函数功能:使用read()函数从文件中提取 n 个字节数据,写入buf指向的地方中
#include <fstream>
#include <iostream>
using namespace std;
void main()
{ char ch[12]; ifstream OpenFile("file.txt"); //需要提前存放好数据文档if (OpenFile.fail()) { cout<<"打开文件错误!"<<endl; exit(0); } OpenFile.read(ch,12); cout<<ch; OpenFile.close(); system("pause");
}
原始建立的文件为:
此种情况原始文件本来就存在一行:
OpenFile.read(ch,12);此中条件下的两种结果:(因为是按照字节读取,整行读取,所以整行数据并未拆分)
将原始文件增加为两行:
OpenFile.read(ch,12);此中条件下的两种结果:
没有读取第二行文本,因为字节数12跟8在限制。
------PS:
1、程序不再使用文件时,为什么要关闭文件?
因为:1)文件缓冲区是一块小的内存空间.
2)操作系统限制同时打开的文件数量
注意:close ( ) 函数关闭文件,但流对象仍然存在。
2、文件的默认打开方式为文本文件,要是想以二进制的方式处理,在打开时要用 ios::binary 显式声明。
3、针对文本文件操作时,get函数和>>的区别:
区别:在读取数据时,get函数包括空白字符(遇空白字符不停止读取)
>>在默认情况下拒绝接受空白字符(遇到空白符停止读取)
4、判断文件是否打开的方法:
//判断文件是否打开的方法:
if (OpenFile)
{ cout<<"打开文件失败!"; exit(0);
}
if (OpenFile.fail())
{ cout<<"打开文件错误!"<<endl; exit(0);
}
5、判断文件是否结束的方法:
//方法1)使用成员函数eof()可以检测到这个结束符,如果非0表示文件结束。while (!OpenFile.eof()) { //文件结束时的代码 }
//2)使用流直接检测,如果为0表示文件结束
while (!OpenFile) { //文件结束时的代码 }
//3)使用get函数,读取最后一个结束符时,返回0.读取正常情况下,返回1,并把读取的字符放到ch中
while ( (OpenFile.get(ch) )!=EOF) { //成功时候的代码 }
文本文件的读写常使用的方法:使用<<写入文件,使用getline 和 >> 读到内存
二进制文件的读写常使用的方法:使用istream 类的成员函数read 和write 来实现,
这两个成员函数的原型为:
istream& read(char *buffer,int len);
ostream& write(const char * buffer,int len);
上述参数说明:字符指针 buffer 指向内存中一段存储空间。len 是读/写的字节数。
与对象结合写入二进制文件时:
//write函数调用语句:
输出文件流对象名.write((char*)& 对象名,sizeof(<对象所属类名>));
输出文件流对象名.write((char*)& 对象数组名[下标],sizeof(<对象所属类名>));
//read函数调用语句:
输入文件流对象名.read((char*)& 对象名,sizeof(<对象所属类名>));
输入文件流对象名.read((char*)& 对象数组名[下标],sizeof(<对象所属类名>));
PS:gcount()函数经常和read函数配合使用,用来获得实际读取的字节数。
//二进制文件的随机读写
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{ //写文件:二进制存储1234 int writeNum1 = 1; int writeNum2 = 2; int writeNum3 = 3; int writeNum4 = 4; ofstream fout("test.txt", ios::out | ios::binary); fout.write(reinterpret_cast<char *>(&writeNum1), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum2), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum3), sizeof(int)); fout.write(reinterpret_cast<char *>(&writeNum4), sizeof(int)); fout.close(); //读文件 ifstream fin("test.txt",ios::in | ios::binary); if (!fin.good()) { cout<<"文件打开错误"<<endl; exit(0); } int readNum = 0; //第一次输出:从第一个数字输出,结果是1 2 3 4 fin.seekg(0,ios::beg); while (fin.peek() != EOF) { fin.read(reinterpret_cast<char*>(&readNum), sizeof(int)); cout<<readNum<<" "; } cout<<endl; //第二次输出:从第三个数字输出,结果是3 4 fin.seekg(2 * sizeof(int),ios::beg);//游标移动的次数 = 需要处理数的个数 × int占的字节数 while (fin.peek() != EOF) { fin.read(reinterpret_cast<char*>(&readNum), sizeof(int)); cout<<readNum<<" "; } cout<<endl; fin.close(); system("pause"); return 0;
}