一、流的概念

  • 数据从内存的一个地址移动到另一个地址称为数据流动——流操作
  • 流操作是通过缓冲区(buffer)机制实现的。
  • 缓冲区:内存的一块区域——用作文件与内存交换数据。
  • 数据从文件中读出:文件 → 缓冲区 → 内存
  • 将数据写入文件:内存 → 缓冲区 → 文件

为什么要使用缓冲区而不直接从文件中读取数据到内存或者直接有内存写入文件呢?我们的文件通常都存在磁盘中,程序从磁盘读取一个字符需要大量的硬件活动,速度非常慢。缓冲方法则从磁盘上读取大量信息,将这些信息存储在缓冲区,然后每次从缓冲区里读取一个字节,因为从内存中读取单个字节的速度比从硬盘上读取快很多,所以这种方法更快,也更方便。说了这么多,只需知道缓冲方法更高效就可以了。

二、流库(stream library)介绍

使用继承的方法建立的输入输出类库,包含两个平行的基本类:streambuf和ios类,所有流类均以两者之一作为基类。

  • streambuf类提供对缓冲区的低级操作:设置缓冲区,对缓冲区指针操作,向缓冲区存取字符等
  • ios类及其派生类提供用户使用流类的接口

本文主要介绍ios,因为ios是编程中几乎必用的类,而streambuf类很少直接使用。下面图片来自网络:

三、文件打开与关闭

  • 当程序中进行文件操作时,应加上头文件“fstream”
  • 若要打开文件进行相应的操作,必须定义相应的流对象。如:ifstream in; // 文件输入流对象,ofstream out; // 文件输出流对象, fstream both; // 文件输入/输出流对象

文件打开用成员函数open();

  • 原型 void(const char * s, ios_base::openmode, mode = ios_base::out|ios_base::trunc)
  • 第一个参数表示打开文件的路径,第二个参数表示文件打开方式,第三个参数表示访问方式,
  • 标志 含义
    ios::ate 打开文件并移动到文件尾
    ios::app 追加到文件尾
    ios:in 作为输入文件(ifstream默认)
    ios::out 作为输出文件(ofstream默认)
    ios::trunc     若文件存在,清除文件内容(默认)
    ios::nocreate 若文件不存在,返回错误
    ios::noreplace 若文件存在,返回错误
    ios::binary 以二进制方式打开

文件打开的方法:

  • 方法一:先定义一个文件流对象,再用文件流对象调用成员函数open( )打开一个文件。如:

       ifstream  f1;  //定义文件输入流对象f1
    f1.open( “d:\\vcprg\\-.cpp”); //打开D盘vcprg文件夹(目录)下的7-3.cpp文件,可进行文件读操作
  • 方法二:在定义文件流对象时利用构造函数打开文件。如:

      ifstream f1( “d:\\vcprg\\-.cpp”)
用文件流对象打开文件后,该对象就代表了被打开的文件。
 #include<iostream>
#include <fstream> using namespace std; void main(void)
{
ifstream f1; //定义文件输入流对象
f1.open("d:\\vcprg\\7-3.cpp"); //打开文件
char c;
while(!f1.eof()) //判断文件未结束则循环,eof()在文件结束时返回true
{
f1.get(c);
cout << c;
}
cout << endl;
f1.close(); //关闭文件
}

文件访问方式:

当用ifstream定义流对象并打开一个文件时,默认为ios_base::in方式;
当用ofstream定义流对象并打开一个文件时,默认为ios_base::out方式;
当用fstream定义流对象并打开一个文件时,应给出打开方式(可用“位或”运算以多种方式打开文件)如:
 fstream f;
f.open(“file.cpp”,ios_base::in|ios_base::out)

例:将D盘vcprg文件夹(目录)下的7-3.cpp文件,复制为text.txt文件。

 #include <iostream>
#include <fstream> using namespace std; void main(void)
{
ifstream f1; //定义文件输入流对象
ofstream f2;
f1.open("d:\\vcprg\\7-3.cpp"); //以读方式打开文件
f2.open("d:\\vcprg\\text.txt"); //以写方式打开文件
char c;
while(!f1.eof()) //判断文件未结束则循环,eof()会在文件结束时返回true
{
f1.get(c);
f2<<c;
}
cout << "文件复制成功" << endl;
f1.close(); //关闭文件
f2.close();
}

文件异常处理:

当打开一个文件可能失败,在程序中通常应加上异常处理程序。

(1) 用条件语句判断文件流标志位failbit是否为true。

if(!文件流对象){<异常处理程序>}

if(文件流对象){<正常处理程序>}(上面一段示例的13行就是用这种方式)

(2)用成员fail()函数

if(文件流对象.fail()){<异常处理程序>}

if(!文件流对象.fail()){<正常处理程序>}

(3)用成员函数good()

if(!文件流对象.good()){<异常处理程序>}

if(文件流对象.good()){<正常处理程序>}

(4)较新的C++实现提供了一种更好的方式is_open()方法,推荐用此方法,但是老式C++没有实现这种方法,用上面三种均可

文件的关闭:

格式:文件流对象.close();

关闭文件操作包括把缓冲区数据完整地写入文件,添加文件结束标志,切断流对象和外部文件的连接
若流对象的生存期没有结束,可以重用
当一个流对象的生存期结束,系统也会自动关闭文件

例如:

 ofstream  ofile ;  // 创建输出文件流

 ofile . open ( "myfile1" ) ; // ofile流与文件“myfile1”相关联

 ……  // 访问文件“myfile1”

 ofile . close ( ) ;  // 关闭文件“myfile1”

 ofile . open ( "myfile2" )  ;   // 重用ofile流

四、文件读写

文本文件的读写:

方法get(char&)和get()提供不跳过空白的单字符输入功能;

方法put(char&)和put()提供不跳过空白的单字符输出功能;

函数get(char*,int,char)和getline(char*,int,char)在默认情况下读取整行;

二进制文件的读写:

二进制文件的读/写分别用成员函数read( )、write( )实现。
写二制文件的格式,输出文件流对象.write((char*)&对象或&对象数组名[下标],sizeof(对象名或所属类名));

读二进制文件的格式,输入文件流对象.read((char*)&对象或&对象数组名[下标],sizeof(对象名或所属类名));
 
使用格式控制(关于格式控制可以参考http://wonderow.cnblogs.com/archive/2005/06/21/178719.html,写得很详细)建立的文本文件:
 #include <fstream>
#include <iomanip> using namespace std; int main ()
{
ofstream ost ;
ost.open ( "d:\\my2.dat" ) ;
ost << "" << endl ;
int a = ;
ost << a << endl ;
ost << setw ( ) << a << endl ;
ost << resetiosflags ( ios :: right ) << setiosflags ( ios :: left )
<< setfill ( '#' ) << setw ( ) << a << endl ;
ost << resetiosflags ( ios :: left ) << setiosflags ( ios :: right )
<< setprecision ( ) << setw ( ) << 12.34567890 << endl ;
ost . close ( ) ;
return ;
}

建立一个包含学生学号、姓名、成绩的文本文件:

 #include <iostream>
#include <fstream>
#include <cstdlib> using namespace std; int main()
{
char fileName[] , name[] ;
int number , score ; ofstream outstuf; //建立输出流对象 cout << "Please input the name of students file :\n" ;
cin >> fileName ; //输入文件名 outstuf.open(fileName, ios::out) ; //以输出方式打开文件 if ( !outstuf )
{
cerr << "File could not be open." << endl ;
exit();
}
outstuf << "学生成绩文件\n" ;
cout << "Input the number, name, and score : (Enter Ctrl-Z to end input)\n? " ;//windows中Ctrl-Z 结束输入和输出 while( cin >> number >> name >> score )
{
outstuf << number << ' ' << name << ' ' << score << '\n' ;
cout << "? " ;
}
outstuf.close() ;
return ;
}

二进制文件,从一个学校教程里搜罗的图,讲的很清晰:

五、总结

  • istream类定义了多个版本的抽取运算符(>>),用于识别所有基本的C++类型,并将字符输入转换为这些类型。get()方法族和getline()方法为单字符输入和字符串输入提供了进一步支持;
  • ostream类定义了多个版本的插入运算符(>>),用于识别所有基本的C++类型,并将字符输入转换为这些类型输出。put()方法为单字符输入和字符串输入提供了进一步支持;
  • 使用ios_base类方法以及文件iostream和iomanip中定义的控制符(参考http://wonderow.cnblogs.com/archive/2005/06/21/178719.html)可以控制格式化输出;
  • 对文件操作,必须将文件与流关联起来,通过ifstream对象与文件关联,可以使用所有istream方法来读取文件,使用ofstream对象与文件关联起来,可以使用ofstream方法来写文件,使用fstream对象关联文件,可以将fstream的输入和输出方法用于文件;
  • 要将文件与流关联,先创建一个文件流对象,然后用open()方法将这个流与文件关联,close()方法终止流与文件的关联;
  • 文本文件是以字符格式存储信息,例如数字值将会被转变为字符表示;
  • seekg()和seekp()通过指针提供对文件的随机存取。tellg()和tellp()方法报告当前文件的位置.

C++学习笔记之输入、输出和文件的更多相关文章

  1. Python基础学习笔记---5.输入\输出 I\O文件操作目录

    在很多时候,你会想要让你的程序与用户(可能是你自己)交互.你会从用户那里得到输入,然后打印一些结果.我们可以分别使用 raw_input 和 print 语句来完成这些功能.对于输出,你也可以使用多种 ...

  2. python学习笔记6-输入输出与文件读取写入

    (1)打印到屏幕:print (2)读取键盘输入:input/raw_input #键盘输入 str = raw_input("Please enter:"); print (&q ...

  3. Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  4. A Byte of Python 笔记(10)输入/输出:文件和储存器

    第12章  输入/输出 大多数情况下,我们需要程序与用户交互.从用户得到输入,然后打印一些结果. 可以分别使用 raw_input 和 print 语句来完成这些功能.对于输出,可以使用多种多样的 s ...

  5. java学习笔记16--I/O流和文件

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note16.html,转载请注明源地址. IO(Input  Output)流 IO流用来处理 ...

  6. tensorflow学习笔记——多线程输入数据处理框架

    之前我们学习使用TensorFlow对图像数据进行预处理的方法.虽然使用这些图像数据预处理的方法可以减少无关因素对图像识别模型效果的影响,但这些复杂的预处理过程也会减慢整个训练过程.为了避免图像预处理 ...

  7. android学习笔记36——使用原始XML文件

    XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...

  8. Linux学习笔记14——使用fcntl实现文件锁定

    期末考试快要来了,Linux学习进度一下拉下来许多.今天学习的是文件锁定,在Linux中,实现文件锁定的方法很多,例如fcntl和lockf.下面主要是fcntl的调用. fcntl函数的原型是:in ...

  9. [Golang学习笔记] 02 命令源码文件

    源码文件的三种类型: 命令源文件:可以直接运行的程序,可以不编译而使用命令“go run”启动.执行. 库源码文件 测试源码文件 面试题:命令源码文件的用途是什么,怎样编写它? 典型回答: 命令源码文 ...

随机推荐

  1. js事件处理相关-实现一个div的拖拽

    最终代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" c ...

  2. hdu 1115(计算多边形重心)

    题意:已知一多边形没有边相交,质量分布均匀.顺序给出多边形的顶点坐标,求其重心. 分析: 求多边形重心的题目大致有这么几种: 1,质量集中在顶点上.n个顶点坐标为(xi,yi),质量为mi,则重心 X ...

  3. JS判断是不是本页面并且,给标签添加属性和属性值

    大多是在导航栏中用到的,在导航栏中在主页和在其他的网页点击导航栏中的主页是不同的,主要就是判断这个. 我是在ascs页面中写的. 下面先看标签: <a href="http://www ...

  4. 改进duilib的richedit控件的部分功能

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41208207 如果要使用透明异形窗体功能,首先要改进duilib库让他本 ...

  5. C++中 类的构造函数理解(一)

    C++中 类的构造函数理解(一) 写在前面 这段时间完成三个方面的事情: 1.继续巩固基础知识(主要是C++ 方面的知识) 2.尝试实现一个iOS的app,通过完成app,学习iOS开发中要用到的知识 ...

  6. C# 实现无焦点窗体(转载)

    #region 无焦点窗体 [System.Runtime.InteropServices.DllImport("user32.dll")] private extern stat ...

  7. nagios为监控图像添加图片

    1. 背景介绍 在监控web页面上显示主机都为问号,如下图所示: 本文的主要目的就是将监控的图片添加进去,让监控图像变得美观. 2. 图片的下载地址 图片的下载地址如下: https://exchan ...

  8. Java中的路径问题

    Java中的路径问题 代码说明,如下: package com.merlin.test; import java.io.InputStream; public class Test { public ...

  9. motan源码解读:注册中心zookeeper(1)

    Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly rel ...

  10. Azure中的分布式1——多实例

    Azure中的WebRole和WorkerRole天然支持负载均衡,只需要简单配置一下即可,下面我以一个WebRole为例说明这一点. 创建一个项目类型为MVC4的WebRole 项目结构如下: 右键 ...