【STL】iostream 编程:输入流成员函数


本文介绍输入流成员函数,包括相关示例。


目录

  • [1 open 函数](#1 open 函数)
  • [2 get 函数](#2 get 函数)
  • [3 getline 函数](#3 getline 函数)
  • [4 read 函数](#4 read 函数)
    • [4.1 概述](#4.1 概述)
    • [4.2 核心关键点](#4.2 核心关键点)
  • [5 seekg 与 tellg 函数](#5 seekg 与 tellg 函数)
  • [6 close 函数](#6 close 函数)

输入流成员函数用于磁盘输入,实现磁盘文件的读取操作。

1 open 函数

使用文件输入流 ifstream 时,需要将流对象磁盘文件进行关联绑定。

有两种实现方式,两种写法的参数规则完全一致

  • 在构造函数中直接传入文件信息打开文件;
  • 或是先创建流对象再调用 open 方法。

打开输入文件时可配置 ios_base::openmode 打开标志,默认打开模式为 ios::in(只读),多个标志之间可以使用按位或运算符 | 组合使用。
打开文件后,调用 fail() 成员函数即可判断文件是否正常打开(返回 true 代表文件不存在或打开失败)。

cpp 复制代码
istream ifile("FILENAME");

if (ifile.fail())
// The file does not exist ...

2 get 函数

无格式成员函数 get 的读取逻辑和提取运算符 >> 大体相似,但存在两点区别:

  1. get 会读取并保留空格、换行等空白字符;系统默认开启 skipws 标志,>> 运算符会自动舍弃空白字符;
  2. 调用 get 时,几乎不会刷新与之绑定的输出流(例如 cout);
    get 存在重载版本:传入字符缓冲区地址 + 最大可读字符数量。该重载用于限制写入数组的数据长度,示例代码如下:
cpp 复制代码
// ioo_get_function.cpp
// compile with: /EHsc
// Type up to 24 characters and a terminating character.
// Any remaining characters can be extracted later.
#include <iostream>
using namespace std;

int main()
{
   char line[25];
   cout << " Type a line terminated by carriage return\n>";
   cin.get( line, 25 );
   cout << line << endl;
}

运行结果:


补充:

  1. 数组大小为 25,最多接收 24 个输入字符,数组最后一位自动填充字符串结束符 \0
  2. 按下的回车(换行符)不会被读入数组,而是残留在输入缓冲区中;
  3. 若输入字符超过 24 位,超出部分会留在缓冲区,不会丢弃,可通过后续输入函数读取;

3 getline 函数

成员函数 getline 与 get 函数用法相近。两个函数都支持传入第三个参数,用来自定义输入的终止字符,默认终止字符为换行符 。二者都会在字符数组里预留一个字节用于存放字符串结束符 \0。

二者关键区别:get 读取停止后,终止字符依旧残留在输入流缓冲区中;而 getline 会读取并丢弃缓冲区里的终止字符。
如下示例为输入流指定了一个终止字符:

cpp 复制代码
// getline_func.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

int main( )
{
   char line[100];
   cout << " Type a line terminated by 't'" << endl;
   cin.getline( line, 100, 't' );
   cout << line;
}

运行结果:

核心对比

特性 cin.get(缓冲区、长度、终止符) cin.getline(缓冲区、长度、终止符)
终止字符 留在输入缓冲区 被读取并丢弃
读取空格 可以读取空格 可以读取空格
数组末尾 自动补 \0 自动补 \0

4 read 函数

4.1 概述

read 成员函数的作用:从文件读取原始字节流,写入到一块指定的内存空间中传入的长度参数用于指定本次需要读取的字节总数。若不指定读取长度,读取行为规则如下:读到文件物理末尾时自动停止;文本模式的文件中,一旦读取到内嵌的 EOF 字符,读取也会立刻停止。
下方实例演示:从薪资文件中读取一条二进制记录,并填充至结构体变量中。

cpp 复制代码
#include <fstream>
#include <iostream>
using namespace std;

int main()
{
   struct
   {
      double salary;
      char name[23];
   } employee;

   ifstream is( "payroll" );
   if( is ) {  // ios::operator void*()
      is.read( (char *) &employee, sizeof( employee ) );
      cout << employee.name << ' ' << employee.salary << endl;
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

程序前提要求:文件内每条数据的存储格式,必须和该结构体在内存中的排布完全一致,文件内部不能存放回车、换行这类文本换行符号。

4.2 核心关键点

  1. 本质:纯粹的二进制整块拷贝
    • read 属于无格式原始读取,不会做任何字符解析、类型转换,只单纯搬运字节,是读写自定义结构体,二进制文件最常用的接口。
  2. 参数解析
    • read(char* 内存起始地址,streamsize 字节数)
    • &employee 是结构体首地址,强制转为 char* 符合函数入参要求;sizeof(employee) 自动算出该结构体占用的总字节数,一次性读完整条记录。
  3. 适用场景
    • 游戏存档、配置二进制文件、结构化数据本地持久化;禁止用在普通文本文件按行读取的场景。
  4. 配套写入对应接口
    • 文件输出流的 write() 和 read() 成对使用,write 把结构体原样写入文件,read 原样读出。
  5. 文本文件换行符干扰
    • 文本文件自带 \r\n 换行标识,会破坏结构体字节对齐,因此存储结构体数据必须用二进制模式打开文件

5 seekg 与 tellg 函数

文件输入流内部维护一个读取位置指针,用来标记下一次读取数据的文件字节位置。seekg 函数可以手动修改该指针的位置

cpp 复制代码
#include <iostream>
#include <fstream>
using namespace std;

int main( )
{
   char ch;

   ifstream tfile( "payroll" );
   if( tfile ) {
      tfile.seekg( 8 );        // Seek 8 bytes in (past salary)
      while ( tfile.good() ) { // EOF or failure stops the reading
         tfile.get( ch );
         if( !ch ) break;      // quit on null
         cout << ch;
      }
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

基本固定记录格式做数据管理时,可以用 【记录序号 * 单条记录字节大小】算出目标字节偏移量,配合 seekg 定位,再读取整条记录。
tellg 成员函数用于获取读取指针当前所在的文件位置,返回值为 streampos (该类型是标准库在 <iostream> 中定义的别名类型)

下面示例遍历文件,并打印出所有空格字符对应的字节位置:

cpp 复制代码
#include <fstream>
#include <iostream>
using namespace std;

int main( )
{
   char ch;
   ifstream tfile( "payroll" );
   if( tfile ) {
       while ( tfile.good( ) ) {
          streampos here = tfile.tellg();
          tfile.get( ch );
          if ( ch == ' ' )
             cout << "\nPosition " << here << " is a space";
       }
   }
   else {
      cout << "ERROR: Cannot open file 'payroll'." << endl;
   }
}

说明:

  1. 命名含义:
    • seekg:seek get → 调整读指针;对应输出流 seekp(seek put 写指针);
    • tellg:tell get → 查询读指针当前坐标;
  2. 典型用途
    • 二进制结构化文件随机读写,不用从头到尾遍历文件就能直接读取指定某一条数据;
  3. 取值范围
    • streampos 本质是封装的整数类型,代表文件相对于文件头部的字节偏移值

6 close 函数

close 成员函数会关闭当前输入流绑定的磁盘文件,同时释放操作系统分配的文件句柄资源

ifstream 对象被销毁时,其析构函数会自动执行文件关闭操作。但如果想要复用同一个流对象去先后打开多个不同的文件,就必须手动调用 close 关闭上一个文件。
补充:

  1. 自动关闭场景

    • 局部的 ifstream 离开作用域销毁 → 析构函数自动 close,绝大多数简单文件读写无需手写 close();
  2. 必须手动 close 的场景

    cpp 复制代码
    ifstream fs;
    fs.open("a.txt");
    fs.close();    //关闭a.txt
    fs.open("b.txt");   //复用 fs 打开新文件 b.txt

    不执行 close 直接 open 新文件会造成文件资源异常

  3. 配套对应

    • ifstream 读文件用 close();ofstream 写文件调用 close 还会强制刷新缓冲区数据写入磁盘
相关推荐
开发者联盟league17 小时前
Java 通过 JNA 调用 C++ DLL:关键流程总结
java·c++·jna
库克克18 小时前
【C++】智能指针
java·开发语言·c++
xiaoye-duck21 小时前
《Linux系统编程》Linux 系统多线程(七): C++ 线程安全日志系统封装:基于策略模式解耦,兼容 glog 使用风格
linux·c++·日志系统
程序喵大人21 小时前
【C++进阶】STL容器与迭代器 - 07 迭代器是容器和算法之间的通用游标
开发语言·c++·算法
汉克老师1 天前
GESP2026年3月认证C++七级( 第三部分编程题(1、拆分))精讲
c++·预处理·dp·取模·gesp7级·数学规律·对数
BerryS3N1 天前
C++在AI时代的核心力量:从底层加速到大规模大模型推理引擎的高能实践
开发语言·c++·人工智能
FlightYe1 天前
音视频修炼之视频基础(一):视频基础理论
android·c++·vscode·音视频·androidx·android runtime
小小帅呀1 天前
CUDA编程实战09:CUDA Graph 实战——降低重复 Kernel 与流水线提交开销
c++·人工智能·矩阵
星恒随风1 天前
C++ STL 详解:map 与 multimap 的使用、operator[]
开发语言·c++·笔记·学习·状态模式