C++文件流读写操作详解

目录
  • 1.打开文件
    • 1.1 fstream类型
    • 1.2 open()的函数原型
    • 1.3 打开方式
    • 1.4 打开文件的属性
    • 1.5 示例代码
  • 2.文本文件的读写
    • 2.1 写文件示例
    • 2.2 读文件示例
    • 2.3 逐字符读取和逐行读取
    • 2.4 统计文本行数及读取某一行内容
    • 2.5 读取数据到数组当中
  • 3.状态标志符的验证(Verification of state flags)
  • 4.获得和设置流指针(get and put stream pointers)
  • 5.二进制文件
  • 6.缓存和同步(Buffers and Synchronization)

1.打开文件

1.1 fstream类型

#include <fstream>
ofstream         //文件写操作 内存写入存储设备
ifstream         //文件读操作,存储设备读区到内存中
fstream          //读写操作,对打开的文件可进行读写操作

1.2 open()的函数原型

void open ( const char * filename,
            ios_base::openmode mode = ios_base::in | ios_base::out );

void open(const wchar_t *_Filename,
        ios_base::openmode mode= ios_base::in | ios_base::out,
        int prot = ios_base::_Openprot);
参数 含义
filename 操作文件名
mode 打开文件的方式
prot 打开文件的属性

1.3 打开方式

打开文件的方式在ios类(所以流式I/O的基类)中定义,有如下几种常用方式:

参数 含义
ios::in 为输入(读)而打开文件
ios::out 为输出(写)而打开文件
ios::ate 初始位置:文件尾
ios::app 所有输出附加在文件末尾
ios::trunc 如果文件已存在则先删除该文件再重新创建
ios::binary 二进制方式

1.4 打开文件的属性

打开文件的属性同样在ios类中也有定义

参数 含义
0 普通文件,打开操作
1 只读文件
2 隐含文件
4 系统文件

1.5 示例代码

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

int main()
{
    ofstream inFile;
    /*ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建*/
    inFile.open("inFile.txt",ios::trunc);

    int i;
    char a='a';
    for(i=1;i<=26;i++)//将26个数字及英文字母写入文件
    {
        inFile<<setw(2)<<i<<"\t"<<a<<"\n";
        a++;
    }
    inFile.close();//关闭文件
}

2.文本文件的读写

2.1 写文件示例

// writing on a text file
 #include <fstream.h>  

 int main ()
 {
     ofstream out(”out.txt”);
     if (out.is_open())
    {
         out << ”This is a line.\n”;
         out << ”This is another line.\n”;
         out.close();
     }
     return 0;
 }
//结果: 在out.txt中写入:
This is a line.
This is another line   

2.2 读文件示例

// reading a text file
   #include <iostream.h>
   #include <fstream.h>
   #include <stdlib.h>  

   int main ()
   {
       char buffer[256];
       ifstream in(”test.txt”);
       if (! in.is_open())
       {
       cout << ”Error opening file”;
       exit (1);
       }
       while (!in.eof() )  //eof到文件末尾返回true
       {
           in.getline (buffer,100);
           cout << buffer << endl;
       }
       return 0;
   }
   //结果 在屏幕上输出
    This is a line.
    This is another line  

2.3 逐字符读取和逐行读取

首先说说getline函数,需要头文件#include<string>

函数原型:istream& getline ( istream &is , string &str , char delim );

其中,istream &is 表示一个输入流,譬如cin;

string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);

char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为'\n',也就是回车换行符

#include <iostream>
#include <fstream>
using namespace std;
void testByChar()
{
    fstream testByCharFile;
    char c;
    testByCharFile.open("inFile.txt",ios::in);
    while(!testByCharFile.eof())
    {
        testByCharFile>>c;
        cout<<c;
    }
    testByCharFile.close();
}
void testByLine()
{
    char buffer[256];
    fstream outFile;
    outFile.open("inFile.txt",ios::in);
    cout<<"inFile.txt"<<"--- all file is as follows:---"<<endl;
    while(!outFile.eof())
    {
        outFile.getline(buffer,256,'\n');//getline(char *,int,char) 表现该行字符达到256个或碰到换行就结束
        cout<<buffer<<endl;
    }
    outFile.close();
}
int main()
{
   cout<<endl<<"逐个字符的读取文件:testByChar() "<<endl<<endl;
   testByChar();
   cout<<endl<<"将文件每行内容存储到字符串中,再输出字符串 :testByLine()"<<endl<<endl;
   testByLine();
}

2.4 统计文本行数及读取某一行内容

//如何统计文本的行数及如何读取文件某一行内容:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int CountLines(char *filename)
{
    ifstream in;
    int n=0;
    string tmp;
    in.open(filename,ios::in);//ios::in 表示以只读的方式读取文件
    if(in.fail())//文件打开失败:返回0
    {
        return 0;
    }
    else//文件存在
    {
        while(getline(in,tmp,'\n'))
        {
            n++;
        }
        in.close();
        return n;
    }
}

string ReadLine(char *filename,int line)
{
    int lines,i=0;
    string temp;
    fstream file;
    file.open(filename,ios::in);
    lines=CountLines(filename);

    if(line<=0)
        return "Error 1: 行数错误,不能为0或负数。";
    if(file.fail())
        return "Error 2: 文件不存在。";
    if(line>lines)
        return "Error 3: 行数超出文件长度。";

    while(getline(file,temp)&&i<line-1)
    {
        i++;
    }
    file.close();
    return temp;
}

int main()
{
    int line;
    char filename[]="inFile.txt";
    cout<<"该文件行数为:"<<CountLines(filename)<<endl;
    cout<<"\n请输入要读取的行数:"<<endl;
    while(cin>>line)
    {
        cout<<"第"<<line<<"行的内容是 :"<<endl;
        cout<<ReadLine(filename,line);
        cout<<"\n\n请输入要读取的行数:"<<endl;
    }
}
/**********************************
程序运行情况如下:
该文件行数为:26
请输入要读取的行数:
-3
第-3行的内容是 :
Error 1: 行数错误,不能为0或负数。
请输入要读取的行数:
4
第4行的内容是 :
 4      d
请输入要读取的行数:
8
第8行的内容是 :
 8      h
请输入要读取的行数:
26
第26行的内容是 :
26      z
请输入要读取的行数:
33
第33行的内容是 :
Error 3: 行数超出文件长度。
请输入要读取的行数:
66
第66行的内容是 :
Error 3: 行数超出文件长度。
请输入要读取的行数:
^Z
**********************************/

2.5 读取数据到数组当中

//读取文件数据到临时数组

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int CountLines(char *filename)
{
    ifstream ReadFile;
    int n=0;
    string tmp;
    ReadFile.open(filename,ios::in);//ios::in 表示以只读的方式读取文件
    if(ReadFile.fail())//文件打开失败:返回0
    {
        return 0;
    }
    else//文件存在
    {
        while(getline(ReadFile,tmp,'\n'))
        {
            n++;
        }
        ReadFile.close();
        return n;
    }
}
int main()
{
    ifstream file;
    int LINES;
    char filename[512]="inFile.txt";
    file.open(filename,ios::in);
    if(file.fail())
    {
        cout<<"文件不存在."<<endl;
        file.close();
    }
    else//文件存在
    {
        LINES=CountLines(filename);
        int *tempInt=new int[LINES];
        char *tempChar=new char[LINES];
        int i=0;
        while(!file.eof()) //读取数据到数组
        {

            file>>tempInt[i];
            file>>tempChar[i];
            i++;
        }
        file.close(); //关闭文件
        for(i=0;i<LINES;i++)//输出数组内容
            cout<<tempInt[i]<<"\t"<<tempChar[i]<<endl;
        delete []tempInt;
        delete []tempChar;
    }
}

3.状态标志符的验证(Verification of state flags)

  • bad() 如果在读写过程中出错,返回 true
    例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候
  • fail()
    除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候
  • eof()
    如果读文件到达文件末尾,返回true
  • good()
    这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false

要想重置以上成员函数所检查的状态标志,你可以使用成员函数clear()

4.获得和设置流指针(get and put stream pointers)

所有输入/输出流对象(i/o streams objects)都有至少一个流指针:

  • ifstream, 类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
  • ofstream, 类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
  • fstream, 类似 iostream, 同时继承了get 和 put

我们可以通过使用以下成员函数来读出或配置这些指向流中读写位置的流指针:

  • tellg() 和 tellp()
    这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前get 流指针的位置 (用tellg) 或 put 流指针的位置(用tellp).
  • seekg() 和seekp()
    这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:
seekg ( pos_type position );
seekp ( pos_type position );

使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。

seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );

使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。它可以是:

参数 含义
ios::beg 从流开始位置计算的位移
ios::cur 从流指针当前位置开始计算的位移
ios::end 从流末尾处开始计算的位移

流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。

使用样例:

例子:
file.seekg(0,ios::beg); //让文件指针定位到文件开头
file.seekg(0,ios::end); //让文件指针定位到文件末尾
file.seekg(10,ios::cur); //让文件指针从当前位置向文件末方向移动10个字节
file.seekg(-10,ios::cur); //让文件指针从当前位置向文件开始方向移动10个字节
file.seekg(10,ios::beg); //让文件指针定位到离文件开头10个字节的位置

获得一个二进制文件的大小:

// obtaining file size
   #include <iostream.h>
   #include <fstream.h>  

   const char * filename = “test.txt”;  

   int main ()
    {
       long l,m;
       ifstream in(filename, ios::in|ios::binary);
       l = in.tellg();
       in.seekg (0, ios::end);
       m = in.tellg();
       in.close();
       cout << ”size of ” << filename;
       cout << ” is ” << (m-l) << “ bytes.\n”;
       return 0;
   }  

  //结果:
  size of example.txt is 40 bytes.  

5.二进制文件

在二进制文件中,使用<< 和>>,以及函数(如getline)来操作符输入和输出数据,没有什么实际意义,虽然它们是符合语法的。

文件流包括两个为顺序读写数据特殊设计的成员函数:write 和 read。第一个函数 (write) 是ostream 的一个成员函数,都是被ofstream所继承。而read 是istream 的一个成员函数,被ifstream 所继承。类 fstream 的对象同时拥有这两个函数。它们的原型是:

write ( char * buffer, streamsize size );
read ( char * buffer, streamsize size );

这里 buffer 是一块内存的地址,用来存储或读出数据。参数size 是一个整数值,表示要从缓存(buffer)中读出或写入的字符数。

读取二进制文件示例:

// reading binary file
    #include <iostream>
    #include <fstream.h>  

    const char * filename = “test.txt”;  

    int main () {
        char * buffer;
        long size;
        ifstream in (filename, ios::in|ios::binary|ios::ate);
        size = in.tellg();
        in.seekg (0, ios::beg);
        buffer = new char [size];
        in.read (buffer, size);
        in.close();  

        cout << ”the complete file is in a buffer”;  

        delete[] buffer;
        return 0;
    }
    //运行结果:
    The complete file is in a buffer  

6.缓存和同步(Buffers and Synchronization)

当我们对文件流进行操作的时候,它们与一个streambuf 类型的缓存(buffer)联系在一起。这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。例如,对于一个输出流, 每次成员函数put (写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。

当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:

  • 当文件被关闭时: 在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。
  • 当缓存buffer 满时:缓存Buffers 有一定的空间限制。当缓存满时,它会被自动同步。
  • 控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush 和endl。
  • 明确调用函数sync(): 调用成员函数sync() (无参数)可以引发立即同步。这个函数返回一个int 值,等于-1 表示流没有联系的缓存或操作失败。

到此这篇关于C++文件流读写操作详解的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解C++编程中的文件流与字符串流

    C++文件流类与文件流对象 文件流是以外存文件为输入输出对象的数据流.输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据.每一个文件流都有一个内存缓冲区与之对应. 请区分文件流与文件的概念,不用误以为文件流是由若干个文件组成的流.文件流本身不是文件,而只是以文件为输入输出对象的流.若要对磁盘文件输入输出,就必须通过文件流来实现. 在C++的I/O类库中定义了几种文件类,专门用于对磁盘文件的输入输出操作. 除了标准输入输出流类istream.ostream和iostream

  • c++读写文件流实例程序讲解

    掌握文本文件读写的方法了解二进制文件的读写方法 C++文件流: 复制代码 代码如下: fstream // 文件流ifstream // 输入文件流ofstream // 输出文件流 //创建一个文本文件并写入信息//同向屏幕上输出信息一样将信息输出至文件#include<iomanip.h>#include<fstream.h>void main(){ ofstream f1("d:\\me.txt"); //打开文件用于写,若文件不存在就创建它 if(!f1

  • C++中输入输出流及文件流操作总结

    本文实例为大家分享了C++中输入输出流及文件流操作笔记,供大家参考,具体内容如下 1.流的控制 iomanip          在使用格式化I/O时应包含此头文件.     stdiostream   用于混合使用C和C + +的I/O机制时,例如想将C程序转变为C++程序 2.类继承关系 ios是抽象基类,由它派生出istream类和ostream类, iostream类支持输入输出操作,iostream类是从istream类和ostream类通过多重继承而派生的类 类ifstream继承了

  • C++文件流读写操作详解

    目录 1.打开文件 1.1 fstream类型 1.2 open()的函数原型 1.3 打开方式 1.4 打开文件的属性 1.5 示例代码 2.文本文件的读写 2.1 写文件示例 2.2 读文件示例 2.3 逐字符读取和逐行读取 2.4 统计文本行数及读取某一行内容 2.5 读取数据到数组当中 3.状态标志符的验证(Verification of state flags) 4.获得和设置流指针(get and put stream pointers) 5.二进制文件 6.缓存和同步(Buffer

  • java高效文件流读写操作详解

    导语 防止自己以后忘记,记录一些文件流的性能对比. 平常经常会操作到文件读写,java当中提供了许多操作文件的类,一般来说,文件操作也叫流操作,可以按照以下方式分类: 按照功能分类,字节流和字符流. 按照节点流和过滤流,节点流直接操作文件,过滤流包装了节点流和过滤流.如FileInputStream和BufferedFileInputStream就是分别是节点流和过滤流. 文件流比较 下面重点比较我们经常用的几个流 (1) DataInputStream+FileInputStream (2)

  • Python YAML文件的读写操作详解

    目录 YAML格式 YAML文件 YAML操作 读取 存储 示例 转字典 转列表 YAML是一种数据序列化格式,方便人类阅读,且容易和脚本语言交互.常用于配置文件,也用于数据存储或传输. YAML格式 YAML三种基本数据类型: 1.标量:如字符串.整数和浮点数.日期 布尔值:“true”.“True”.“TRUE”.“yes”.“Yes"和"YES”,“false”.“False”.“FALSE”.“no”.“No"和"NO” 空:null.Null.~或不指定值

  • Java Zip文件读写操作详解

    输入流(读取): ZipInputStream是一种FileInputStream流,它可以直接读取Zip压缩包的内容: ┌───────────────────┐│    InputStream    │└───────────────────┘          ▲          │┌───────────────────┐│ FilterInputStream │└───────────────────┘          ▲          │┌──────────────────

  • 对python for 文件指定行读写操作详解

    1.os.mknod("test.txt") #创建空文件 2.fp = open("test.txt",w) #直接打开一个文件,如果文件不存在则创建文件 3.关于open 模式: 详情: w:以写方式打开, a:以追加模式打开 (从 EOF 开始, 必要时创建新文件) r+:以读写模式打开 w+:以读写模式打开 (参见 w ) a+:以读写模式打开 (参见 a ) rb:以二进制读模式打开 wb:以二进制写模式打开 (参见 w ) ab:以二进制追加模式打开 (

  • Pandas对CSV文件读写操作详解

    目录 什么是 CSV 文件 CSV 库解析 CSV 文件 读取 CSV 文件 CSV reader 参数 CSV 文件的写入 使用 pandas 库解析 CSV 文件 pandas 读取 CSV 文件 pandas 写入 CSV 文件 什么是 CSV 文件 CSV 文件(逗号分隔值文件)是一种纯文本文件,它使用特定的结构来排列表格数据.因为它是一个纯文本文件,所以只能包含实际的文本数据,换句话说就是可打印的 ASCII 或 Unicode 字符. 通常,CSV 文件的结构由其名称给出,使用逗号分

  • Go语言学习笔记之文件读写操作详解

    目录 文件写 文件读 小结 文件操作比较多,分为几篇来写吧.首先是文件的读写,在平时的工程化操作中使用最多. 文件写 样例代码如下 package main import ( "bufio" "fmt" "io" "os" ) //写文件 func DoWriteFile() error { _filePath := "./test.txt" _file, _err := os.OpenFile(_file

  • C++文件读写操作详解

    目录 一.读写文本文件 1.1 写文件 1.2读文件 二.读写二进制文件 2.1 写文件 2.2 读文件 一.读写文本文件 1.1 写文件 写文件步骤如下: 包含头文件 #include <fstream> 创建流对象 ofstream ofs; 打开文件 ofs.open("文件路径",打开方式); 写数据 ofs << "写入的数据"; 关闭文件 ofs.close(); 文件打开方式: 打开方式 解释 ios::in 为读文件而打开文件

  • IOS 文件读写操作详解及简单实例

    iPhone 文件读写操作 1,写文件操作 - (IBAction)btnWrite:(id)sender { //创建文件管理器 NSFileManager *fileManager = [NSFileManager defaultManager]; //获取路径 //参数 要获取的哪种路径 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSSt

  • Node.js Streams文件读写操作详解

    Node.js 天生异步和事件驱动,非常适合处理 I/O 相关的任务.如果你在处理应用中 I/O 相关的操作,你可以利用 Node.js 中的流(stream).因此,我们先具体看看流,理解一下它们是怎么简化 I/O 操作的吧. 流是什么 流是 unix 管道,让你可以很容易地从数据源读取数据,然后流向另一个目的地. 简单来说,流不是什么特别的东西,它只是一个实现了一些方法的 EventEmitter .根据它实现的方法,流可以变成可读流(Readable),可写流(Writable),或者双向

随机推荐