`
WindMill
  • 浏览: 15771 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

C++文件处理详解

阅读更多
转摘于:http://hi.baidu.com/nahxa/blog/item/2667978f046889ebf01f369f.html

C++ 通过以下几个类支持文件的输入输出:

    * ofstream: 写操作(输出)的文件类 (由ostream引申而来)
    * ifstream: 读操作(输入)的文件类(由istream引申而来)
    * fstream: 可同时读写操作的文件类 (由iostream引申而来)


打开文件(Open a file)

对这些类的一个对象所做的第一个操作通常就是将它和一个真正的文件联系起来,也就是说打开一个文件。被打开的文件在程序中由一个流对象(stream object)来表示 (这些类的一个实例) ,而对这个流对象所做的任何输入输出操作实际就是对该文件所做的操作。

要通过一个流对象打开一个文件,我们使用它的成员函数open():
void open (const char * filename, openmode mode);

这里filename 是一个字符串,代表要打开的文件名,mode 是以下标志符的一个组合:
ios::in 为输入(读)而打开文件
ios::out 为输出(写)而打开文件
ios::ate 初始位置:文件尾
ios::app 所有输出附加在文件末尾
ios::trunc 如果文件已存在则先删除该文件
ios::binary 二进制方式

这些标识符可以被组合使用,中间以”或”操作符(|)间隔。例如,如果我们想要以二进制方式打开文件"example.bin" 来写入一些数据,我们可以通过以下方式调用成员函数open()来实现:
ofstream file;
file.open ("example.bin", ios::out | ios::app | ios::binary);

ofstream, ifstream 和 fstream所有这些类的成员函数open 都包含了一个默认打开文件的方式,这三个类的默认方式各不相同:
类 参数的默认方式
ofstream ios::out | ios::trunc
ifstream ios::in
fstream ios::in | ios::out

只有当函数被调用时没有声明方式参数的情况下,默认值才会被采用。如果函数被调用时声明了任何参数,默认值将被完全改写,而不会与调用参数组合。

由于对类ofstream, ifstream 和 fstream 的对象所进行的第一个操作通常都是打开文件,这些类都有一个构造函数可以直接调用open 函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:
ofstream file ("example.bin", ios::out | ios::app | ios::binary);

两种打开文件的方式都是正确的。

你可以通过调用成员函数is_open()来检查一个文件是否已经被顺利的打开了:
bool is_open();

它返回一个布尔(bool)值,为真(true)代表文件已经被顺利打开,假( false )则相反。

关闭文件(Closing a file)

当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据排放出来并关闭文件。它的格式很简单:
void close ();

这个函数一旦被调用,原先的流对象(stream object)就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程(process)所有访问了。

为防止流对象被销毁时还联系着打开的文件,析构函数(destructor)将会自动调用关闭函数close。

文本文件(Text mode files)

类ofstream, ifstream 和fstream 是分别从ostream, istream 和iostream 中引申而来的。这就是为什么 fstream 的对象可以使用其父类的成员来访问数据。

一般来说,我们将使用这些类与同控制台(console)交互同样的成员函数(cin 和 cout)来进行输入输出。如下面的例题所示,我们使用重载的插入操作符<<:
    // writing on a text file
    #include <fiostream.h>
    
    int main () {
        ofstream examplefile ("example.txt");
        if (examplefile.is_open()) {
            examplefile << "This is a line.\n";
            examplefile << "This is another line.\n";
            examplefile.close();
        }
        return 0;
    }

 

file example.txt
This is a line.
This is another line.

从文件中读入数据也可以用与 cin的使用同样的方法:
    // reading a text file
    #include <iostream.h>
    #include <fstream.h>
    #include <stdlib.h>
    
    int main () {
        char buffer[256];
        ifstream examplefile ("example.txt");
        if (! examplefile.is_open())
        { cout << "Error opening file"; exit (1); }
        while (! examplefile.eof() ) {
            examplefile.getline (buffer,100);
            cout << buffer << endl;
        }
        return 0;
    }

  

This is a line.
This is another line.

上面的例子读入一个文本文件的内容,然后将它打印到屏幕上。注意我们使用了一个新的成员函数叫做eof ,它是ifstream 从类 ios 中继承过来的,当到达文件末尾时返回true 。

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

除了eof()以外,还有一些验证流的状态的成员函数(所有都返回bool型返回值):

    * bad()

      如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。
    * fail()

      除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。
    * eof()

      如果读文件到达文件末尾,返回true。
    * good()

      这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

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

获得和设置流指针(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 的返回值进行修改。对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生。

以下例子使用这些函数来获得一个二进制文件的大小:
    // obtaining file size
    #include <iostream.h>
    #include <fstream.h>
    
    const char * filename = "example.txt";
    
    int main () {
        long l,m;
        ifstream file (filename, ios::in|ios::binary);
        l = file.tellg();
        file.seekg (0, ios::end);
        m = file.tellg();
        file.close();
        cout << "size of " << filename;
        cout << " is " << (m-l) << " bytes.\n";
        return 0;
    }

  

size of example.txt is 40 bytes.

二进制文件(Binary files)

在二进制文件中,使用<< 和>>,以及函数(如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 = "example.txt";
    
    int main () {
        char * buffer;
        long size;
        ifstream file (filename, ios::in|ios::binary|ios::ate);
        size = file.tellg();
        file.seekg (0, ios::beg);
        buffer = new char [size];
        file.read (buffer, size);
        file.close();
        
        cout << "the complete file is in a buffer";
        
        delete[] buffer;
        return 0;
    }

  

The complete file is in a buffer

缓存和同步(Buffers and Synchronization)

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

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

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

相关推荐

    C++文件操作详解(详细讲述fstream类的使用)

    讲解文件操作的类fstream 并对ifstream和ofstream一并做讲解

    visual c++数字图像处理技术详解part4(随书光盘)

    数字图像处理技术的研究和应用离不开程序设计,VisualC++则是最强大、最常用的数字图像处理程序开发工具之一。visual c++数字图像处理技术详解光盘文件

    Visual C++ MFC编程详解和实例

    3.6 MFC怎样处理一个接收到的消息 36 3.7 处理用户界面的对象 44 3.8 创建自定义窗口消息 45 3.8.1 静态分配的窗口消息 45 3.8.2 动态分配的窗口消息 46 3.9 重定向消息 47 3.9.1 子分类和超分类 47 3.9.2 用MFC子...

    Visual C++ 6.0编程实例详解.part1

    1.1 MFC与C++ 1.2 VC++组件 1.3 安装 1.3.1 环境 1.3.2 安装过程 第2章 开发环境 2.1 主窗口 2.2 工具栏 2.2.1 Shaod工具栏 2.2.2 Build Mini-bar工具栏 2.3 菜单栏 2.3.1 File菜单 ...

    C++简述小程序

    再看程序的第1行“#include ”,这不是C++的语句,而是C++的一个预处理命令,它以“#”开头以与C++语句相区别,行的末尾没有分号。#include 是一个“包含命令”,它的作用是将文件iostream的内容包含到该命令所在的程序...

    解析png文件格式C++源码

    解析png文件格式,详细处理png各个chunk,且可设定idat 压缩等级。vc-analytic png file format, every detail png chunk, idat which can be set compression level.

    Visual C++串口通信技术详解.(机械工业.李景峰.杨丽娜.潘恒)

    书名:《Visual C++串口通信技术详解》(机械工业出版社.李景峰.杨丽娜.潘恒) PDF格式扫描版,全书分为16章,共368页。2010年6月出版。 内容简介 本书介绍如何利用Visual C++集成开发环境进行串口通信程序开发。书...

    Visual C++数字图像模式识别技术详解(书籍+源码)

    经典的《Visual C++数字图像模式识别技术详解》,包含清晰完整的PDF电子书和随书光盘(内含详细源代码),由于文件太大,分三部分上传

    《Visual C++数字图像处理开发入门与编程实践》源码

    第1章 Visual C++与数字图像处理 1 1.1 数字图像处理概述 2 1.1.1 图像与数字图像 2 1.1.2 数字图像处理研究的内容 4 1.1.3 数字图像处理的应用 6 1.2 Visual C++概述 8 1.2.1 C++语言简介 8 1.2.2 Visual C++简介 ...

    Visual C++数字图像模式识别技术详解(part2)

    经典的《Visual C++数字图像模式识别技术详解》,包含清晰完整的PDF电子书和随书光盘(内含详细源代码),由于文件太大,分三部分上传

    Visual C++ 数字图像处理技术详解光盘(14章)

    先打开一幅图片然后按照顺序灰度化、二值化、灰度拉伸、车牌定位、二值化、倾斜校正、字符分割、训练神经网络、识别字符。 测试图像存储在当前目录的img下。...测试集、训练集、目标向量均存储在img下的文本文件中。

    [PDF带章节书签]《Visual C++游戏开发经典案例详解》part1

    《Visual C++游戏开发经典案例详解》 作者:王浩 本书配套光盘中提供了作者专门为本书录制的多媒体语音教学视频和本书所涉及的源代码,这些源代码都经过精心调试,在Windows 2000 /XP/ 2003下测试通过。 本书中的各...

    Visual c++数字图像处理技术(刘海波)第2版光盘——part1

    Visual c++数字图像处理技术(刘海波)第2版光盘——part1.。。。文件太大,分三部分上传

    精通visual c++图像处理技术与工程案例

    详细介绍Visual C++数字图像编程。通过大量的综合性实例,向读者展示了如何开发一套完整的数字图像处理应用程序。  包含数字图像处理的基本技术和典型应用,然后介绍了9个综合性的商业案例,分别是相机自动调焦系统...

    hadoop 读写文件流程详解

    在hadoop中,有三大法宝——HDFS,MapReduce,Hbase,但是无论是MapReduce,Hbase还是hadoop中的其他组件如:Hive等他们要处理的数据还是处理完了的数据都是存储在HDFS中。可见HDFS可以说是hadoop存储的基础和核心,...

    Visual C++ 6.0编程实例详解.part2

    1.1 MFC与C++ 1.2 VC++组件 1.3 安装 1.3.1 环境 1.3.2 安装过程 第2章 开发环境 2.1 主窗口 2.2 工具栏 2.2.1 Shaod工具栏 2.2.2 Build Mini-bar工具栏 2.3 菜单栏 2.3.1 File菜单 ...

    《VisualC++数字图像处理技术详解》光盘代码 1-13章

    《VisualC++数字图像处理技术详解》光盘代码 1-13章 本书以数字图像处理技术为主线,全面地介绍在Visual C++环境下进行数字图像处理程序设计的方法。内容涵盖了数字图像的变换、增强、复原、重建、形态学处理、分割...

    Visual C++.NET案例开发集锦

    从简单的控件应用到复杂的数据库函数,从本地应用到复杂的网络处理都详细地进行了剖析,涵盖了C++编程基础、图形图像处理、多媒体应用、系统文件处理、硬件的控制、数据库、网络处理等多个方面,本着循序渐进、...

    Visual C++数字图像处理(第二版)光盘

    VISUAL C++经典初级,CDROM,源代码

    Qt/C++中使用OCX控件的调用方法及事件处理代码实例

    Qt/C++中使用OCX控件的调用方法及事件处理 代码实例简单的调用了OCX提供的函数,和OCX事件处理(采用了信号与槽的方式),调用qt的方法获取列出所有ocx控件的所有信号、函数、属性等。 谢谢大家的分享和分数,我很...

Global site tag (gtag.js) - Google Analytics