IE盒子

搜索
查看: 123|回复: 1

【C++】I/O概念框架:流、缓冲区、文件

[复制链接]

1

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2022-12-29 15:22:06 | 显示全部楼层 |阅读模式
流(stream)

C++程序把输入和输出看作字节流。

  • 输入时,程序从输入流中抽取字节;输入流中的字节可能来自键盘、存储设备(如硬盘)或其他程序;
  • 输出时,程序将字节插入到输出流中;输出流中的字节可以流向屏幕、打印机、存储设备或其他程序。
流充当了程序和流源或流目标之间的桥梁。这使得C++程序可以以相同的方式对地来自键盘的输入和来自文件的输入,C++程序只是检查字节流,而不需要知道字节来自何方;C++处理输出的方式也将独立于其去向。
缓冲区

通常,通过使用缓冲区可以更高效地处理输入和输出。缓冲区是用作中介地内存块,它是将信息从设备传输到程序或从程序传输给设备地临时存储工具。
1.从磁盘文件读写的情况

通常,像磁盘驱动器这样的设备以512字节(或更多)的块为单位来传输的块为单位来传输信息,而程序通常每次只能处理一个字节的信息。缓冲区帮助匹配这两种不同的信息传输速率
假设程序要计算记录在硬盘文件中的金额。如果程序直接从文件中一个一个读取字符,处理一个字符后,再从文件中读取下一个字符,再处理。以此类推。
但是从磁盘文件中每次读取一个字符需要大量的硬件活动,速度非常慢。
缓冲方法则从磁盘上读取大量信息,将这些信息存储在缓冲区中,然后程序每次从缓冲区里读取一个字节。因为从内存中读取单个字节的速度比硬盘上读取快很多,所以这种方式更快,也更方便。
当然,到达缓冲区尾部后,程序将继续从磁盘上读取另一块数据。
输出时,程序首先填满缓冲区,然后把整块数据传输到硬盘,并清空缓冲区,以备下一批输出使用。这被称为刷新缓冲区flushing the buffer)。
2.从键盘读的情况

键盘输入每次提供一个字符,因此在这种情况下,程序无需缓冲区来帮助匹配不同的数据传输速率。
然而,对键盘输入进行缓冲可以让用户在将输入传输给程序之前返回并更正。

  • C++程序通常在用户按下回车键时候刷新输入缓冲区
  • 对于屏幕输出,C++程序通常在用户发送换行符刷新输出缓冲区
程序也可能会在其他情况下刷新输入,例如输入即将到来时,这取决于实现。也就是说,当程序到达输入语句时,它将刷新输出缓冲区中当前所有的输出(与ANSI C一致的C++实现是这样工作的)。
iostream文件与流、缓冲区

管理流和缓冲区的工作有点复杂,但iostream文件中包含一些专门设计用来实现、管理流和缓冲区的类。



一些I/Q类


  • streambuf类为缓冲区提供了内存,并提供了用于填充缓冲区、访问缓冲区的内容、刷新缓冲区和管理缓冲区内存的类方法;
  • ios_base类表示流的一般特征,如是否可读取、是二进制流还是文本流等;
  • ios类基于ios_base,其中包括了一个指向streambuf对象的指针成员;
  • ostream类是从ios类派生而来的,提供了输出方法;
  • istream类也是从ios类派生而来的,提供了输入方法;
  • iostream类是基于istream和ostream类的,因此继承了输入方法和输出方法。
要使用这些工具,必须使用适当的类对象。例如,使用ostream对象(如cout)来处理输出。创建这样的对象将打开一个流,自动创建缓冲区,并将其与流关联起来,同时使得能够使用类成员函数。
现在,ios基类中的一些独立于类型的信息被移动到新的ios_base类中,这包含各种格式化常量,例如ios::fixed(现在为ios_base::fixed)。另外,ios_base还包含了一些老式ios中没有的选项。
C++的iostream类库管理了很多细节。例如,在程序中包含iostream文件将自动创建8个流对象(4个用于窄字符流,4个用于宽字符流)。

  • cin对象对应于标准输入流。在默认情况下,这个流被关联到标准输入设备(通常为键盘)。wcin对象与此类似,但处理的是wchar_t类型。
  • cout对象与标准输出流相对应。在默认情况下,这个流被关联到标准输出设备(通常为显示器)。wcout对象与此类似,但处理的是wchar_t类型。
  • cerr对象与标准错误流相对应,可用于显示错误消息。在默认情况下,这个流被关联到标准输出设备(通常为显示器)。这个流没有被缓冲,这意味着信息将被直接发送给屏幕,而不会等到缓冲区填满或新的换行符。werr对象与此相似,但处理的是wchar_t类型。
  • clog对象也对应着标准错误流。在默认情况下,这个流被关联到标准输出设备(通常为显示器)。这个流被缓冲。wclog对象与此相似,但处理的是wchar_t类型。
总之,流的一端与程序相连,另一端与标准输出相连,cout对象凭借streambuf对象的帮助,管理着流中的字符流。
重定向(<和>)

标准输入和输出流通常连接着键盘和屏幕。但很多操作系统(包括UNIX、Linux和Windows)都支持重定向,这个工具使得能够改变标准输入和标准输出。
例如,假设有一个名为counter.exe的、可执行的Windows命令提示符C++程序,它能够计算输入中的字符数,并报告结果。程序运行情况如下:
// 在命令提示符窗口中运行
C>counter
**Hello
and goodbye!
Control-Z**    << simulated end-of-file
Input contained 19 characters.
C>其中的输入来自键盘,输出的被显示到屏幕上。
通过输入重定向(<)和输出重定向(>),可以使用上述程序计算文件“oklahoma”中的字符数,并将结果放到”cow_cnt”文件中:
C>counter <oklahoma >cow_cnt
C>

  • 命令行中的<oklahoma将标准输入与oklahoma文件关联起来,使cin从该文件(而不是键盘)读取输入。换句话说,操作系统改变了输入流的流入端连接,而流出端仍然与程序相连。
  • 命令行中的>cow_cnt将标准输出与cow_cnt文件关联起来,导致cout将输出发送给文件(而不是屏幕)。也就是说,操作系统改变了输出流的流出端连接,而流入端仍与程序相连。
DOS、Windows命令提示符模式、Linux和UNIX能自动识别这种重定向语法

  • cout代表的标准输出流是程序输出的常用通道。
  • 标准错误流(由cerr和clog代表)用于程序的错误消息。
默认情况下,这3个对象都被发送给显示器。但对标准输出重定向并不会影响cerr或clog,因此,如果使用其中一个对象来打印错误消息,程序将在屏幕上显示错误消息,即使常规的cout输出被重定向到其他地方。
std::cout << "Here come the goodies!\\n";
std::cerr << "Something horrible has happened.\\n";

  • 如果重定向没有起作用,则选定的消息都将被显示在屏幕上
  • 如果程序输出被重定向到一个文件,则第一条消息将被发送到文件中,而第二条消息将被发送到屏幕。
有些操作系统也允许对标准错误进行重定向。例如,在UNIX和Linux中,运算符2>重定向标准错误。
[1] 《C++ Primer Plus》第17章
回复

使用道具 举报

3

主题

12

帖子

25

积分

新手上路

Rank: 1

积分
25
发表于 2025-5-15 07:33:50 | 显示全部楼层
呵呵,低调,低调!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表