本文介绍输入流成员函数,包括相关示例。
目录
- [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 的读取逻辑和提取运算符 >> 大体相似,但存在两点区别:
- get 会
读取并保留空格、换行等空白字符;系统默认开启 skipws 标志,>> 运算符会自动舍弃空白字符;- 调用 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;
}
运行结果:
补充:
- 数组大小为 25,最多接收 24 个输入字符,数组最后一位自动填充字符串结束符 \0;
- 按下的回车(换行符)不会被读入数组,而是残留在输入缓冲区中;
- 若输入字符超过 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 核心关键点
- 本质:纯粹的二进制整块拷贝
- read 属于无格式原始读取,不会做任何字符解析、类型转换,只单纯搬运字节,是读写自定义结构体,二进制文件最常用的接口。
- 参数解析
- read(char* 内存起始地址,streamsize 字节数)
- &employee 是结构体首地址,强制转为 char* 符合函数入参要求;sizeof(employee) 自动算出该结构体占用的总字节数,一次性读完整条记录。
- 适用场景
- 游戏存档、配置二进制文件、结构化数据本地持久化;禁止用在普通文本文件按行读取的场景。
- 配套写入对应接口
- 文件输出流的 write() 和 read() 成对使用,write 把结构体原样写入文件,read 原样读出。
- 文本文件换行符干扰
- 文本文件自带 \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;
}
}
说明:
- 命名含义:
seekg:seek get → 调整读指针;对应输出流 seekp(seek put 写指针);tellg:tell get → 查询读指针当前坐标;- 典型用途
- 二进制结构化文件
随机读写,不用从头到尾遍历文件就能直接读取指定某一条数据;- 取值范围
- streampos 本质是封装的整数类型,
代表文件相对于文件头部的字节偏移值;
6 close 函数
close 成员函数会关闭当前输入流绑定的磁盘文件,同时释放操作系统分配的文件句柄资源 。
ifstream 对象被销毁时,其析构函数会自动执行文件关闭操作。但如果想要复用同一个流对象去先后打开多个不同的文件,就必须手动调用 close 关闭上一个文件。
补充:
自动关闭场景
- 局部的 ifstream 离开作用域销毁 →
析构函数自动 close,绝大多数简单文件读写无需手写 close();必须手动 close 的场景
cppifstream fs; fs.open("a.txt"); fs.close(); //关闭a.txt fs.open("b.txt"); //复用 fs 打开新文件 b.txt
不执行 close 直接 open 新文件会造成文件资源异常。配套对应
- ifstream 读文件用 close();ofstream 写文件调用 close 还会
强制刷新缓冲区数据写入磁盘;

