Linux C\C++方式下的文件I/O编程

ops/2025/1/22 7:50:49/

【图书推荐】《Linux C与C++一线开发实践(第2版)》_linux c与c++一线开发实践pdf-CSDN博客

《Linux C与C++一线开发实践(第2版)(Linux技术丛书)》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 

LinuxC\C++编程技术_夏天又到了的博客-CSDN博客

4.9.1  流的概念

在C++语言中,数据的输入和输出包括对标准输入设备(键盘)和标准输出设备(显示器)、外存磁盘上的文件以及内存中指定的字符串存储空间(当然可用该空间存储任何信息)进行输入输出。对标准输入设备和标准输出设备的输入输出简称为标准I/O,对外存磁盘上的文件的输入输出简称为文件I/O,对内存中指定的字符串存储空间的输入输出简称为(字符)串I/O。

“流”就是“流动”,是物质从一处向另一处流动的过程。C++流是指信息从外部输入设备(如键盘和磁盘)向计算机内部(即内存)输入和从内存向外部输出设备(如显示器和磁盘)输出的过程,这种输入输出过程被形象地比喻为“流”。为了实现信息的内外流动,C++系统定义了I/O类库,其中的每一个类都称作相应的流或流类,用以完成某一方面的功能。一个流类定义的对象也时常被称为流。例如根据文件流类fstream定义的一个对象fio可称作fio流或fio文件流,用它可以同磁盘上的一个文件相联系,实现对该文件的输入和输出,fio就等同于与之相联系的文件。

因为C++兼容C,所以C中的输入输出函数依然可以在C++中使用,但是很显然,直接把C的那套输入输出搬到C++中肯定无法满足C++的需求,更重要的一点是,C中的输入输出有类型要求,只支持基本类型,因此C++设计了易于使用的并且多种输入输出流接口统一的I/O类库,并且支持多种格式化操作,还可以自定义格式化操作。总体来说,C++中有3种输入输出流。

(1)标准I/O流:内存与标准输入输出设备之间信息的传递。

(2)文件I/O流:内存与外部文件之间信息的传递。

(3)字符串I/O流:内存变量与表示字符串流的字符数组之间信息的传递。

C++引入I/O流,将这3种输入输出流接口统一起来,使用符号“>>”读取数据的时候,不用去管是从何处读取数据,使用符号“<<”写数据的时候,也不需要管是写到哪里去。

4.9.2  流的类库

C++语言系统为实现数据的输入和输出定义了一个庞大的类库,其中ios为根基类,其余都是它的直接或间接派生类,它直接派生4个类:输入流类istream、输出流类ostream、文件流基类fstreambase和字符串流基类strstreambase。C++系统中的I/O类库的所有类被包含在iostream、fstream和strstream这3个系统头文件中。我们可以用图4-4来表示各个类的继承关系。

图4-4

头文件<fstream>提供了3个文件流类:ifstream、ofstream和fstream。

值得注意的是,要在C++中进行文件处理,必须在C++源码文件中包含头文件<fstream>。此外,在C++新标准中,头文件都把.h去掉了,如#include<fstream.h>现在要用:

#include<fstream> using namespace std; 

同时要把标准命名空间加上。但是fstream.h和fstream并不是完全等价的。在旧头文件里的fstream.h,如果使用ifstream file的默认参数声明一个输入文件流,当这个要读的file文件不存在时,会自动创建一个空文件,从而给判断文件是否存在造成了很多麻烦。如果使用新标准fstream,就不会创建空文件,从而可以用while(!file)来判断文件是否存在,通过返回数值来指导程序运行。

类似地,头文件ostream.h与iostream也是不同的。iostream.h在旧的C++标准中使用,新标准中用iostream,还要引用命名空间std。iostream.h慢慢地不再使用了,比如微软的VC6可以使用iostream.h,VS 2008已经不能使用iostream.h了。好像不习惯将没有.h 结尾的文件称为头文件,但与时俱进吧,头文件不一定要.h。

4.9.3  打开文件

在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream和fstream对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,就使用ifstream对象。被打开的文件在程序中由一个流对象来表示(这些类的一个实例),而对这个流对象所做的任何输入输出操作实际上就是对该文件所做的操作。要通过一个流对象打开一个文件,需要使用它的成员函数open()。open()函数是fstream、ifstream和ofstream对象的一个成员,该函数声明如下:

void open(const char *filename, ios::openmode mode);

其中,第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。文件打开模式如表4-3所示。

可以把以上两种或两种以上的模式结合使用。例如,如果想要以写入模式打开文件,并希望截断文件,以防止文件已存在,那么可以使用下面的代码:

ofstream outfile;outfile.open("file.dat", ios::out | ios::trunc );

类似地,如果想要打开一个文件用于读写,可以使用下面的代码:

fstream  afile;afile.open("file.dat", ios::out | ios::in );

又比如,如果想要以二进制方式打开文件example.bin来写入一些数据,可以这样写:

ofstream file;file.open ("example.bin", ios::out | ios::app | ios::binary);

ofstream、ifstream和fstream类的成员函数open都包含一个默认打开文件的方式,这3个类的默认方式各不相同,如表4-4所示。

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

由于对类ofstream、ifstream和fstream的对象所进行的第一个操作通常都是打开文件,因此这些类都有一个构造函数可以直接调用open函数,并拥有同样的参数。这样,我们就可以通过以下方式进行与上面同样的定义对象和打开文件的操作:

ofstream file ("example.bin", ios::out | ios::app | ios::binary); // 定义对象的同时直接打开文件

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

另外,我们可以通过调用成员函数is_open(),来检查一个文件是否已经被顺利地打开了:

bool is_open();

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

4.9.4  关闭文件

当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据释放出来并关闭文件。close()函数是fstream、ifstream和ofstream对象的一个成员函数,声明如下:

void close();

这个函数一旦被调用,原先的流对象就可以被用来打开其他的文件了,这个文件也就可以重新被其他的进程访问了。为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close()。

4.9.5  写入文件

在C++编程中,我们使用流插入运算符(<<)向文件写入数据,就像使用该运算符输出信息到屏幕上一样。唯一不同的是,在这里使用的是ofstream或fstream对象,而不是cout对象。

4.9.6  读取文件

在C++编程中,我们使用流提取运算符(>>)从文件读取信息,就像使用该运算符从键盘输入信息一样。唯一不同的是,在这里使用的是ifstream或fstream对象,而不是cin对象。

下面来看一个例子,以读写模式打开一个文件。在向文件afile.dat写入用户输入的信息之后,程序从文件读取信息,并将其输出到屏幕上。

【例4.13】用C++流的方式读写文件

(1)打开Visual Studio Code,新建文本文件test.cpp,输入代码如下:

#include <fstream>
#include <iostream>
using namespace std;int main ()
{char data[100];// 以写模式打开文件ofstream outfile;outfile.open("afile.dat");cout << "Writing to the file" << endl;cout << "Enter your name: "; cin.getline(data, 100);// 向文件写入用户输入的数据outfile << data << endl;cout << "Enter your age: "; cin >> data;cin.ignore();// 再次向文件写入用户输入的数据outfile << data << endl;// 关闭打开的文件outfile.close();// 以读模式打开文件ifstream infile; infile.open("afile.dat"); cout << "Reading from the file" << endl; infile >> data; // 在屏幕上写入数据cout << data << endl;// 再次从文件读取数据,并显示它infile >> data; cout << data << endl; // 关闭打开的文件infile.close();return 0;
}

(2)上传test.cpp到Linux,在终端下输入命令g++ -o test test.cpp,然后运行test,结果如下:

# g++ -o test test.cpp
# ./test
Writing to the file
Enter your name: zww
Enter your age: 61
Reading from the file
zww
61

可以看到在同目录下生成了一个文件afile.dat,查看里面的内容可得:

# cat afile.dat
zww
61

上面的例子中使用了cin对象的附加函数,比如getline()函数从外部读取一行,ignore()函数会忽略掉之前读语句留下的多余字符。


http://www.ppmy.cn/ops/152136.html

相关文章

Data Filtering Network 论文阅读和理解

目录 一、TL&#xff1b;DR 二、Introduction 2.1 apple的结论 2.2 业界做法&#xff1a; 2.3 我们的做法&#xff08;Apple&#xff09; 2.4 如何获取好的DFN 三、未完待续&#xff08;这周出去购物了&#xff0c;下周继续补充&#xff09; 一、TL&#xff1b;DR 核心…

【Pandas】pandas Series rolling

Pandas2.2 Series Function application, GroupBy & window 方法描述Series.apply()用于将一个函数应用到 Series 的每个元素或整个 SeriesSeries.agg()用于对 Series 数据进行聚合操作Series.aggregate()用于对 Series 数据进行聚合操作Series.transform()用于对 Series…

c# PDF文件合并工具

界面 主要用于发票PDF文件的合并。经常出差要报销的很有用。 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System…

【RabbitMQ 消息丢失常见情况分析】

RabbitMQ 消息丢失分析:常见场景与解决策略 RabbitMQ 作为一种流行的消息队列中间件,广泛应用于各类分布式系统中。它通过发布/订阅模式解耦了生产者和消费者,提高了系统的可扩展性和可靠性。然而,在实际应用中,消息丢失仍然是一个亟待关注的问题。本文将探讨导致 Rabbit…

Android studio开发实战之碎片Fragment

一、碎片化的概念 碎片化&#xff08;Fragment&#xff09;是 Android 应用开发中的一个重要概念&#xff0c;它的设计初衷是增强界面模块化&#xff0c;便于开发者灵活构建和管理复杂的界面。 什么是模块化&#xff1f; 将应用界面拆分成多个可复用的小模块&#xff08;Fragm…

Vue平台开发三——项目管理页面

前言 对于多个项目的使用&#xff0c;可能需要进行项目切换管理&#xff0c;所以这里创建一个项目管理页面&#xff0c;登录成功后跳转这个页面&#xff0c;进行选择项目&#xff0c;再进入Home页面展示对应项目的内容。 一、实现效果图预览 二、页面内容 功能1、项目列表展…

Mybatis 进阶 / Mybatis—Puls (详细)

目录 一.动态SQL 1.1标签 1.2 标签 1.3标签 1.4标签 1.5标签 1.6标签 mybatis总结&#xff1a; 二.Mybatis-Puls 2.1准备工作 2.2CRUD单元测试 2.2.1创建UserInfo实体类 2.2.2编写Mapper接⼝类 2.2.3 测试类 2.3 常见注解 2.3.1TableName 2.3.2TableField 2.4打印日…

Vue3 中使用组合式API和依赖注入实现自定义公共方法

组合式API 1.在项目根目录 src 文件夹下创建文件夹 utils &#xff0c;创建 index.js 文件 2.抛出想要对外暴露的方法&#xff0c;以下是一个判断数据类型的方法 export function getType(params) {// 判断是否是基本类型let res typeof paramsif (res ! object) {return re…