fstream的操作

第一段转载自:https://blog.csdn.net/jaster_wisdom/article/details/52400059

在C++中输入输出到指定文件,或者从指定文件中读出数据使用fstream类较为方便。

1.将数据写到磁盘的指定文件中

首先第一步是加头文件#include <fstream>,引入库函数

第二步,声明一个ofstream对象,调用ofstream的成员函数open函数,与指定的文件相关联

第三步,使用<<向文件中写入数据,注意<<操作符已经在库函数里重载过,所以直接调用即可。

最后一步,关闭输出流,调用close()函数


   
   
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main(){
  5. ofstream outfile;
  6. outfile.open( “D:\\data.txt”);
  7. outfile<< “随机产生的序列:”<< endl;
  8. for( int i= 0;i< 10;i++){
  9. outfile<<i<< endl;
  10. }
  11. outfile.close();
  12. return 0;
  13. }

在D盘data.txt文件中,应该是这样的效果:


注意,这里的data.txt文件可以提前创建,当然也可以有程序自动创建,也就是说当程序执行到该步时,发现该目录下没有该文件,那么会自动地生成一个文本文件。

在这里有时候会出现这样的问题,当我的代码是这样的:


   
   
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main(){
  5. ofstream outfile;
  6. outfile.open( "D:\\data.txt");
  7. outfile<< "随机产生的序列:"<< endl;
  8. for( int i= 0;i< 10;i++){
  9. outfile<<i<< " "; //注意这行与上面的区别
  10. }
  11. outfile.close();
  12. return 0;
  13. }

本意是想将数字横着输出一行,那么到底有没有实现这样的功能呢?

这里要分情况,如果是Dev或者其他比较流行的编译器,是没有任何问题的,效果如下:


但如果是Microsoft visual 6.0这种比较老式的编译器,就会出现这样的情况:


很明显,数字不见了。在此声明,这种情况只会在比较老式的编译器中出现。

原因是要写入的数据在缓冲区内,还没有保存到文本中,解决办法是写完之后刷新一次,调用flush()函数来清空缓冲区。


   
   
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main(){
  5. ofstream outfile;
  6. outfile.open( "D:\\data.txt");
  7. outfile<< "随机产生的序列:"<< endl;
  8. for( int i= 0;i< 10;i++){
  9. outfile<<i<< " "; //注意这行与上面的区别
  10. }
  11. outfile.flush();
  12. outfile.close();
  13. return 0;
  14. }
这里需要说明一下原理:

当程序向输出设备中输出数据时,输出的数据先被存放在计算机缓冲区(Buffer)内。当缓冲区存满时,这些数据才真正地输出到输出设备。但是,如果输出的字符序列中出现了endl控制符,那么缓冲区内的所有数据将立即输出到输出设备,而无论缓冲区是否已经存满。因此,endl的作用将光标移动到输出设备中下一行开头处,并且清空缓冲区。
很有可能,出现在程序终止时,并没有输出所有的输出数据的情况。这是因为在程序终止时,缓冲区不一定是满的,所有也就没有将缓冲区的数据写到输出设备。
在C++中,可以使用flush函数来清空缓冲区,即使缓冲区中的数据不是满的。


2.将磁盘文件中的数据读到控制台

原理和写到文件类似,就是一个逆过程。


   
   
  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. int main(){
  5. ifstream infile;
  6. infile.open( "D:\\data.txt");
  7. string str;
  8. infile >> str;
  9. cout<<str<< endl;
  10. infile.close();
  11. return 0;
  12. }



以下文章转载于:https://blog.csdn.net/seadplus/article/details/7802346

C++文件流:


  
  
  1. fstream   // 文件流
  2. ifstream  // 输入文件流
  3. ofstream  // 输出文件流

 

 


  
  
  1. #include <fstream>
  2. //创建一个文本文件并写入信息
  3. //同向屏幕上输出信息一样将信息输出至文件
  4. #include<iomanip.h>
  5. #include<fstream>
  6. void main()
  7. {
  8. ofstream ofs("C:\\example.txt");            //打开文件用于写,若文件不存在就创建它
  9. if (!ofs) return;                   //打开文件失败则结束运行
  10. f1 << setw( 20) << "Name: " << "Beethoven" << endl;     //使用插入运算符写文件内容
  11. f1 << setw( 20) << "song: " << "Moonlight Sonata" << endl;
  12. f1.close();                   //关闭文件
  13. }



文件操作:
打开文件

文件名
注意路径名中的斜杠要双写,如:
“D:\\MyFiles\\ReadMe.txt”

文件打开方式选项:


  
  
  1. ios::in    = 0x01,  //供读,文件不存在则创建(ifstream默认的打开方 式)
  2. ios::out    = 0x02,  //供写,文件不存在则创 建,若文件已存在则清空原内容(ofstream默认的打开方式)
  3. ios::ate    = 0x04,  //文件打开时,指针在文件最后。可改变指针的位置,常和in、out联合使用
  4. ios::app    = 0x08,  //供写,文件不存在则创建,若文件已存在则在原文件内容后写入 新的内容,指针位置总在最后
  5. ios::trunc   = 0x10,  // 在读写前先将文件长度截断为0(默认)
  6. ios::nocreate = 0x20,  //文件不存在时产生错误,常和in或app联合使用
  7. ios::noreplace = 0x40,  //文件存在时产生错误,常和out联合使用
  8. ios::binary  = 0x80  //二进制格式文件


文件保护方式选择项:


  
  
  1. filebuf::openprot;    //默认的兼容共享方式
  2. filebuf::sh_none;    //独占,不共享
  3. filebuf::sh_read;    //读共享
  4. filebuf::sh_write;    //写共享


打开文件的方法
调用构造函数时指定文件名和打开模式


  
  
  1. ifstream f("d:\\12.txt", ios::nocreate);         //默认以 ios::in 的方式打开文件,文件不存在时操作失败
  2. ofstream f("d:\\12.txt");                //默认以 ios::out的方式打开文件
  3. fstream  f("d:\\12.dat", ios::in|ios::out|ios::binary);  //以读 写方式打开二进制文件


使用Open成员函数


  
  
  1. fstream f;
  2. f.open( "d:\\12.txt",ios::out);              //利用同一对象对多个文件进行操作时要用到open函数



检查是否成功打开
成功:


  
  
  1. if (f) {...}        //对ifstream、ofstream对象可 用,fstream对象不可用。 mysql
  2. if (f.good()) {...}


失败:


  
  
  1. if (!f) {...}       // !运算符已经重载
  2. if (f.fail()) {...}

 

读写操作
使 用<<,>>运算符
只能进行文本文件的读写操作,用于二进制文件可能会产生错误。
使用函数成员 get、put、read、write等
经常和read配合使用的函数是 gcount(),用来获得实际读取的字节数。

读写二进制文件注意事项
打开方式中必须指定ios::binary,否则读写会出错
用read\write进行读写操作,而不能使用插入、提取运算符进行操作,否则 会出错。
使用eof()函数检测文件是否读结束,使用gcount()获得实际读取的字节数

关闭文件
使用成员函数close, 如: oracle
f.close(); 
利用析构函数
对象生命期结 束时会检查文件是否关闭,对没有关闭的文件进行关闭操作。

随机读写文件
通过移动文件读写指针,可在文件指定位置进行读写。


  
  
  1. seekg(绝对位置);       //绝对移动,    //输入流操作
  2. seekg(相对位置,参照位置);  //相对操作
  3. tellg();           //返回当前指针位置
  4. seekp(绝对位置);       //绝对移动,    //输出流操作
  5. seekp(相对位置,参照位置);  //相对操作   
  6. tellp();           //返回当前指针位置


参照位置: mysql


  
  
  1. ios::beg  = 0       //相对于文件头
  2. ios::cur   = 1       //相对于当前位置
  3. ios::end  = 2       //相对于文件尾

 

 写文本文件的示例
//为能够正确读出写入文件的各数据,各数据间最好要有分隔


  
  
  1. #include <fstream>
  2. void main()
  3. {
  4. fstream f("d:\\try.txt", ios::out);
  5. f << 1234 << ' ' << 3.14 << 'A' << "How are you"; //写入数据
  6. f.close();
  7. f.open(" d:\\ try.txt", ios::in);
  8. int i;
  9. double d;
  10. char c;
  11. char s[ 20];
  12. f >> i >> d >> c;               //读取数据
  13. f.getline(s,20);
  14. cout << i << endl;             //显示各数据
  15. cout <<d << endl;
  16. cout << c << endl;
  17. cout << s << endl;
  18. f.close();
  19. }


运 行结果:
1234
3.14
A
How are you
Press any key to continue

显示文本文件的内容


  
  
  1. //使用get()一次读一个字符--------------------------------方案一
  2. #include <fstream>
  3. void main()
  4. {
  5. ifstream fin("d:\\简介.txt", ios::nocreate);
  6. if (!fin) {
  7. cout << "File open error!\n";
  8. return;
  9. }
  10. char c;
  11. while ((c=fin.get()) != EOF) cout << c;    //注意结束条件的判断
  12. fin.close();
  13. }


//使用get(char *,int n,char delim=’\n’)一次读多个字符—-方案二
//巧妙利用文本文件中不会有字符’\0’的特点进行读取


  
  
  1. #include<fstream>
  2. void main()
  3. {
  4. ifstream fin("d:\\简介.txt",ios::nocreate);
  5. if(!fin){
  6. cout<< "File open error!\n";
  7. return;
  8. }
  9. char c[ 80];
  10. while(fin.get(c, 80, '\0')!= NULL) cout<<c; //注意结束条件的判断
  11. fin.close();
  12. }
  13. //使用read(char *,int n)读文件---------------------------方案三
  14. #include<fstream.h>
  15. void main()
  16. {
  17. ifstream fin("d:\\简介.txt",ios::nocreate);
  18. if(!fin){
  19. cout<< "File open error!\n";
  20. return;
  21. }
  22. char c[ 80];
  23. while(!fin.eof())            //判 断文件是否读结束
  24. {
  25. fin.read(c, 80);
  26. cout.write(c,fin.gcount());
  27. }
  28. fin.close();
  29. }


 

拷贝文件
//二进制文件操作示例 ssh


  
  
  1. #include<fstream>
  2. void main()
  3. {
  4. ifstream fin("C:\\1.exe", ios::nocreate|ios::binary);
  5. if (!fin) {
  6. cout << "File open error!\n";
  7. return;
  8. }
  9. ofstream fout("C:\\2.exe", ios::binary);
  10. char c[ 1024];
  11. while (!fin.eof())
  12. {
  13. fin.read(c, 1024);
  14. fout.write(c, fin.gcount());
  15. }
  16. fin.close();
  17. fout.close();
  18. cout << "Copy over!\n";
  19. }


 一个打开并检查输入文件的程序:


  
  
  1. #include<iostream>
  2. #include<fstream>
  3. #include<string>
  4. using namespace std;
  5. ifstream& open_file(ifstream &in,const string &file)
  6. {
  7. in.close();
  8. in.clear();
  9. in.open(file.c_str());
  10. return in;
  11. }
  12. int main()
  13. {
  14. ifstream file;
  15. open_file(file, "1.txt");
  16. string s;
  17. while(getline(file,s))
  18. {
  19. cout<<s<< endl;
  20. }
  21. file.close();
  22. return 0;
  23. }


 

以下补充内容转载于:https://www.cnblogs.com/shaoguobao/archive/2011/04/15/2017413.html 主要对fstream的格式以及put,get,read,write函数进行补充

ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间; 
在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:
1、插入器(<<) 
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<”Write Stdout”<<’\n’;就表示把字符串”Write Stdout”和换行字符(’\n’)输出到标准输出流。 
2、析取器(>>) 
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的类型)的数据。 
  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类的文件操作过程一一道来。 
一、打开文件 
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是: 
void open(const char* filename,int mode,int access); 
参数: 
filename:  要打开的文件名 
mode:    要打开文件的方式 
access:   打开文件的属性 
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:

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

可以用“或”把以上属性连接起来,如ios::out|ios::binary
打开文件的属性取值是:
0:普通文件,打开访问 
1:只读文件 
2:隐含文件 
4:系统文件
可以用“或”或者“+”把以上属性连接起来,如3或1|2就是以只读和隐含属性打开文件。 
例如:以二进制输入方式打开文件c:\config.sys

   
   
fstream file1;
file1.open( ” c:\\config.sys ” ,ios::binary | ios:: in , 0 );

如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:

   
   
file1.open( ” c:\\config.sys ” ); <=> file1.open( ” c:\\config.sys ” ,ios:: in | ios:: out , 0 );

另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了: 

   
   
fstream file1( ” c:\\config.sys ” );
特别提出的是,fstream有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。

   
   
ifstream file2( ” c:\\pdos.def ” ); // 以输入方式打开文件
ofstream file3( ” c:\\x.123 ” ); // 以输出方式打开文件

  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用fstream来定

二、关闭文件 
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。 
三、读写文件 
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式 
  1、文本文件的读写 
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下: 

   
   
file2 << ” I Love You ” ; // 向文件写入字符串”I Love You”
int i;
file1 >> i; // 从文件输入一个整数值。


这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些 
操纵符 功能 输入/输出 
dec 格式化为十进制数值数据 输入和输出 
endl 输出一个换行符并刷新此流 输出 
ends 输出一个空字符 输出 
hex 格式化为十六进制数值数据 输入和输出 
oct 格式化为八进制数值数据 输入和输出 
setpxecision(int p) 设置浮点数的精度位数 输出 

比如要把123当作十六进制输出:
file1<<hex<<123;
要把3.1415926以5位精度输出:
file1<<setpxecision(5)<<3.1415926;
  2、二进制文件的读写 
①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个字符时终止。 
③读写数据块 
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型下:

   
   
read(unsigned char * buf, int num);
write( const unsigned char * buf, int num);
read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。 
例: 
复制代码
   
   
unsigned char str1[] = " I Love You " ;
int n[ 5 ];
ifstream in ( " xxx.xxx " );
ofstream out ( " yyy.yyy " );
out .write(str1,strlen(str1)); // 把字符串str1全部写到yyy.yyy中
in .read((unsigned char * )n, sizeof (n)); // 从xxx.xxx中读取指定个整数,注意类型转换
in .close();
out .close();
复制代码

四、检测EOF 
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof(); 
例:  if(in.eof()) ShowMessage(“已经到达文件尾!”); 
五、文件定位 
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和seekp()。seekg()是设置读位置,seekp是设置写位置。它们最通用的形式如下: 
   
   
    istream & seekg(streamoff offset,seek_dir origin);
    ostream & seekp(streamoff offset,seek_dir origin);

  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举: 
ios::beg:  文件开头 
ios::cur:  文件当前位置 
ios::end:  文件结尾 
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。例: 
   
   
   file1.seekg( 1234 ,ios::cur); // 把文件的读指针从当前位置向后移1234个字节
   file2.seekp( 1234 ,ios::beg); // 把文件的写指针从文件开头向后移1234个字节
fstream的用法 
开一个文件 
fstream f; 
f.open(“1.txt”, ios::in | ios::binary); 
if (!f.is_open()) // 检查文件是否成功打开 
    cout << “cannot open file.” << endl; 
ios::in与ios::bianry均为int型,定义文件打开的方式。 
ios::in – 打开文件用于读。 
ios::out – 打开文件用于写,如果文件不存在,则新建一个;存在则清空其内容。 
ios::binary – 以二进制bit流方式进行读写,默认是ios::text,但最好指定这种读写方式,即使要读写的是文本。因为在ios::text模式下,在写入时’\ n’字符将转换成两个字符:回车+换行(HEX: 0D 0A) 写入,读入时作逆转换,这容易引起不必要的麻烦。ios::app – 打开文件在文件尾进行写入,即使使用了seekp改变了写入位置,仍将在文件尾写入。 
ios::ate – 打开文件在文件尾进行写入,但seekp有效。 
读写位置的改变 
f.seekg(0, ios::beg); // 改变读入位置 g mean Get 
f.seekp(0, ios::end); // 改变写入位置 p mean Put 
第一个参数是偏移量offset(long),第二个参数是offset相对的位置,三个值: 
ios::beg – 文件头    ios::end – 文件尾    ios::cur – 当前位置 

文件读写 
char s[50]; 
f.read(s, 49); 
s[50] = ’\0’; // 注意要自己加上字符串结束符 
char *s = “hello”; 
f.write(s, strlen(s)); 
补充    记得读写完成后用f.close()关闭文件。 
例子    下面的程序用于删除带有行号的源程序中的行号。


复制代码
   
   
#include < iostream >
#include < fstream >
using namespace std;
// 定义要删除的行号格式,下面定义的是型如: #0001 的行号
const int LINE_NUM_LENGTH = 5 ;
const char LINE_NUM_START = ’#’;
int main( int argc, char * argv[])
{
fstream f;
char * s = NULL;
int n;
for ( int i = 1 ; i < argc; i ++ ) {
cout << " Processing file " << argv[i] << " ...... " ;
f.open(argv[i], ios:: in | ios::binary);
if ( ! f.is_open()){
cout << " CANNOT OPEN " << endl;
continue ;
}
f.seekg( 0 , ios::end);
n = f.tellg(); // 文件大小
s = new char [n + 1 ];
f.seekg( 0 , ios::beg);
f.read(s, n);
s[n] = ’\ 0 ’;
f.close();
// 采用一种简单的判断,遇到LINE_NUM_START后接一个数字,
// 则认为它是一个行号.
for ( int j = 0 ; j < n; j ++ ) {
if (s[j] == LINE_NUM_START && (s[j + 1 ] >= ’ 0 ’ && s[j + 1 ] <= ’ 9 ’)) {
for ( int k = j; k < j + LINE_NUM_LENGTH; k ++ )
s[k] = ’ ’;
}
}
f.open(argv[i], ios:: out | ios::binary);
if ( ! f.is_open()) {
cout << " CANNOT OPEN " << endl;
delete[] s;
continue ;
}
f.write(s, n);
f.close();
cout << " OK " << endl;
delete[] s;
}
return 0 ;
复制代码

(文章来源于网络)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值