100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > C++文件流fstream相关操作

C++文件流fstream相关操作

时间:2023-07-01 06:11:09

相关推荐

C++文件流fstream相关操作

C++文件流fstream相关操作

一、理解Open函数

利用fstream,使用open/close打开或创建,完成后关闭,对文件读入读出使用插入器(<<) 或析取器(>>)完成。参考C++文件写入、读出函数。

函数void open(…)参数选项

在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:void open(const char* filename, int mode, int access);

打开文件的方式mode在类ios(是所有流式I/O类的基类)中定义,可以用“或”把以上属性连接起来,如 ios::out | ios::binary 常用的值如下:

ios::app: 以追加的方式打开文件 ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性 ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文 ios::in: 文件以输入方式打开(文件数据输入到内存) ios::out: 文件以输出方式打开(内存数据输出到文件) ios::nocreate: 不建立文件,所以文件不存在时打开失败 ios::noreplace: 不覆盖文件,所以打开文件时如果文件存在失败 ios::trunc: 如果文件存在,把文件长度设为0

打开文件的属性access取值如下,可以用“或”或者“+”把以上属性连接起来,如3 或 1|2就是以只读和隐含属性打开文件。

0:普通文件,打开访问 1:只读文件 2:隐含文件 4:系统文件

C++文件流fstream相关操作

一、理解Open函数

利用fstream,使用open/close打开或创建,完成后关闭,对文件读入读出使用插入器(<<) 或析取器(>>)完成。参考C++文件写入、读出函数。

函数void open(…)参数选项

在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:void open(const char* filename, int mode, int access);

打开文件的方式mode在类ios(是所有流式I/O类的基类)中定义,可以用“或”把以上属性连接起来,如 ios::out | ios::binary 常用的值如下:

ios::app: 以追加的方式打开文件

ios::ate: 文件打开后定位到文件尾,ios:app就包含有此属性

ios::binary: 以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文

ios::in: 文件以输入方式打开(文件数据输入到内存)

ios::out: 文件以输出方式打开(内存数据输出到文件)

ios::nocreate: 不建立文件,所以文件不存在时打开失败

ios::noreplace: 不覆盖文件,所以打开文件时如果文件存在失败

ios::trunc: 如果文件存在,把文件长度设为0

打开文件的属性access取值如下,可以用“或”或者“+”把以上属性连接起来,如3 或 1|2就是以只读和隐含属性打开文件。

0:普通文件,打开访问

1:只读文件

2:隐含文件

4:系统文件

2. 功能及应用场景

如果open函数只有文件名一个参数,则是以读/写普通文件打开, 即:file1.open(“c:\config.sys”); <=> file1.open(“c:\config.sys”, ios::in | ios::out, 0); 只读模式(fstream::out)可以创建新文件

1)文件新建并写入

如果该文件不存在则新建并写入,如果该文件存在则清除所有内容并从头开始写入;选择使用的参数:ios::trunc | ios::out | ios::in。

fstream _file;_file.open(FILENAME, ios::in);if(!_file) //或者_file.fail == true or _file.is_open == truecout<<FILENAME<<"没有被创建!"<<endl;elsecout<<FILENAME<<"已经存在!"<<endl;

ofstream my_samplefile ("my_saple.txt",ios::trunc|ios::out|ios::in );

2)写入CSV文件

CSV文件有其特殊性,由于逗号分隔符的存在,写入文件时只需要注意不遗漏必要的逗号,即可生成格式化的CSV文件。需要注意的是在open打开或创建的文件,务必以“.csv”后缀结束。

#include <iostream>#include <fstream>#include <string>#include <vector>#include <algorithm>#include <random>using namespace std;int main(){std::random_device rd; //obtain a seedstd::mt19937 gen(rd()); //mersenne_twister_enginestd::uniform_real_distribution<> dist(-1.0, 1.0);ofstream outFile;outFile.open("test5000.csv", ios::out);// 5000*128for(int i=1;i<=5000;i++){for(int j=1;j<=127;j++){outFile << dist(gen) << ',';}outFile <<dist(gen) <<endl;}outFile.close();}

3)其它应用

贴一个简单的日志处理程序:

#include <iostream>#include <fstream>//LP:增加日志void TestComLog(std::string strTxt){std::ofstream wObj;wObj.open(".\\log\\NetTest0827.txt", std::ios::app);wObj << strTxt << std::endl;wObj.close();} ///< ssl 上下文

二、文件读写 & 文件格式化

ofstream是从内存到硬盘,ifstream是从硬盘到内存。文件读写的步骤:1、包含的头文件:#include 。2、创建流。3、打开文件(文件和流关联)。4、读写 (写操作:<<,put( ), write( ) 读操作: >> , get( ),getline( ), read( ))。5、关闭文件:把缓冲区数据完整地写入文件, 添加文件结束标志, 切断流对象和外部文件的连接。

操纵符 功能 输入/输出

dec 格式化为十进制数值数据 输入和输出 endl 输出一个换行符并刷新此流 输出(关闭文件输出流) ends 输出一个空字符 输出 hex 格式化为十六进制数值数据 输入和输出 oct 格式化为八进制数值数据 输入和输出 setpxecision(int p) 设置浮点数的精度位数 输出

二进制文件的读写

①put() put()函数向流写入一个字符

其原型是ofstream &put(char ch),使用也比较简单,如file1.put(‘c’);就是向流写一个字符’c’。

②get() get()函数比较灵活,有3种常用的重载形式:

一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中读取一个字符,并把读取的字符保存在x中。

另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。

还有一种形式的原型是:ifstream &get(char *buf,int num,char delim=’\n’);这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符’\n’。例如:file2.get(str1,127,‘A’); //从文件中读取字符到字符串str1,当遇到字符’A’或读取了127个字符时终止。

针对文本文件操作时,get函数和>>的区别:

区别:在读取数据时,get函数包括空白字符(遇空白字符不停止读取)

>>在默认情况下拒绝接受空白字符(遇到空白符停止读取)

③读写数据块

要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:

istream& read(unsigned char *buf,int num);ostream& write(const unsigned char *buf,int num);

read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。

成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();

文件定位

和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置, seekp是设置写位置。它们最通用的形式如下:

1 istream &seekg(streamoff offset,seek_dir origin); //设置读位置2 ostream &seekp(streamoff offset,seek_dir origin); //设置写位置

streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举.

基准位置:

ios::beg:文件开头ios::cur:文件当前位置ios::end:文件结尾

这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。

//指针移到文件的最前面seekg(0) ;//把当前的指针当作0seekg(0,ios::cur);//将指针移到文件尾,若再配合file.tellg()则可以求出文件的大小为多少bytes。seekg(0,ios::end);

考虑一个本地数据记录的文件写入格式,或一个类似log4cpp的日志写入功能如何实现。

使用运算符<<(写)和getline()进行读写

<<:以行为单位输入文件,getline():以行为单位 读入内存,能一次读入一行

函数原型:istream &getline( char *buffer, streamsize num );功能:getline( )函数用于从文件读取num-1个字符到buffer(内存)中,直到下列情况发生时,读取结束:1):num - 1个字符已经读入2):碰到一个换行标志3):碰到一个EOF

三、文件指定行数删除或更新

文件的删除和重命名比较简单,但是以下两个操作都必须在文件关闭后才可以使用

1 //把这个文件删除2 remove("文件名”);3 rename("旧文件名","新文件名");

全部读出到自定义缓存区,修改缓存区某一行后再覆盖写入

主要思路可选getline函数读取行数据,并计数。修改可以分为两种,一种是定长修改,一种是长度发生变化的修改。两种修改都有一种通用的修改方法,不过这个方法非常没有效率,那就是建立一个tmp文件,把修改过后的内容放到里面,然后删掉原文件把tmp文件改成原文件的名字。这个方法可用但显然不是很科学,而且如果文件内容很大,那么执行效率低下时间可能会挺长的,除了文件长度较小的场景外并不推荐使用。修改文件打开属性,定长修改指定数据

不定长修改某行后,其文件指针会移动,因此会影响到这行后面的部分,所以修改的时候不能该表指定行的长度。如果使用ios::app来打开文件,虽然不会清空文件内容,但是每次写操作都追加到文件末尾(app模式为追加写入),指针偏移操作无效,即使你seekp无效,参考C++ 修改/覆盖指定位置的文件内容或者从某个位置开始截断文件(里面部分细节表述不准确,但是总体思路是对的)。以下内容转载自关于fstream修改文件内容的操作,操作的方法和注意事项比较扼要。

(1)在进行文件写的时候(非二进制),文件指针很成问题。举个例子:比如文件的内容是"100100100",写入了三个int类型的变量,值为100。接下来我如果想改变第二个100,使其变成200,文件指针需要移动3位,因为前面有三个字符。这时候指针是一个字符一个字符的移动的。

#include <iostream>#include <fstream>using namespace std;int main(){ofstream ofs("cece.txt", ios::out);int x = 100;ofs << x << x << x;ofs.close();ofs.open("cece.txt", ios::out | ios::in);x = 200;ofs.seekp(3);ofs << x;}

(2)而如果把文件换成二进制的写,那么情况就会有些变化,如果还是想改写第二个100的内容,那么文件指针就需要指向sizeof(int)。指针是一个byte一个byte地移动。 int存入的方式就是以int类型,将其原封写入文件,所以二进制的读写比较简单。

#include <iostream>#include <fstream>using namespace std;int main(){ofstream ofs("cece.txt", ios::out | ios::binary);int x = 100;ofs.write((char *)&x, sizeof(x));ofs.write((char *)&x, sizeof(x));ofs.write((char *)&x, sizeof(x));ofs.close();ofs.open("cece.txt", ios::out | ios::in | ios::binary);x = 200;ofs.seekp(sizeof(int));ofs.write((char *)&x, sizeof(x));}

(3)经实验表明,ios::app Mode下是不能移动文件指针的,而且这个时候tellp()是0。此模式下只能在后面追加着写。

(4).如果想要获得指向末尾的位置指针,需要

ofs.seekp(0, ios::end);pointer = ofs.tellp();

这个时候如果文件内没有内容,那么pointer的值会是-1。等长修改就是这样,不等长修改的话,如果长度小于原来,可以写进去,然后添0,或者别的,大于原来的,目前只会tmp覆盖原文件的方法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。