C++用read()和write()读写二进制文件的超详细教程

目录
  • 前言
  • C++ ostream::write()方法写文件
  • C++ istream::read()方法读文件
  • 总结

前言

通过前一节的学习,读者了解了以文本形式读写文件和以二进制形式读写文件的区别,并掌握了用重载的 >> 和 << 运算符实现以文本形式读写文件。在此基础上,本节继续讲解如何以二进制形式读写文件。

不过介绍具体的实现方法前,先给读者介绍一下相比以文本形式读写文件,以二进制形式读写文件有哪些好处?

举个例子,现在要做一个学籍管理程序,其中一个重要的工作就是记录学生的学号、姓名、年龄等信息。这意味着,我们需要用一个类来表示学生,如下所示:

class CStudent
{
    char szName[20];  //假设学生姓名不超过19个字符,以 '\0' 结尾
    char szId[l0];  //假设学号为9位,以 '\0' 结尾
    int age;  //年龄
};

前面章节中,我们学会了如何以文本形式读写文件,如果使用此方式存储学生的信息,则最终的文件中存储的学生信息可能是这个样子:

Micheal Jackson 110923412 17
Tom Hanks 110923413 18

要知道,这种存储学生信息的方式不但浪费空间,而且后期不利于查找指定学生的信息(查找效率低下),因为每个学生的信息所占用的字节数不同。

这种情况下,以二进制形式将学生信息存储到文件中,是非常不错的选择,因为以此形式存储学生信息,可以直接把 CStudent 对象写入文件中,这意味着每个学生的信息都只占用 sizeof(CStudent) 个字节。

值得一提的是,要实现以二进制形式读写文件,<< 和 >> 将不再适用,需要使用 C++ 标准库专门提供的 read() 和 write() 成员方法。其中,read() 方法用于以二进制形式从文件中读取数据;write() 方法用于以二进制形式将数据写入文件。

C++ ostream::write()方法写文件

ofstream 和 fstream 的 write() 成员方法实际上继承自 ostream 类,其功能是将内存中 buffer 指向的 count 个字节的内容写入文件,基本格式如下:

ostream & write(char* buffer, int count);

其中,buffer 用于指定要写入文件的二进制数据的起始位置;count 用于指定写入字节的个数。

也就是说,该方法可以被 ostream 类的 cout 对象调用,常用于向屏幕上输出字符串。同时,它还可以被 ofstream 或者 fstream 对象调用,用于将指定个数的二进制数据写入文件。

同时,该方法会返回一个作用于该函数的引用形式的对象。举个例子,obj.write() 方法的返回值就是对 obj 对象的引用。

需要注意的一点是,write() 成员方法向文件中写入若干字节,可是调用 write() 函数时并没有指定这些字节写入文件中的具体位置。事实上,write() 方法会从文件写指针指向的位置将二进制数据写入。所谓文件写指针,是是 ofstream 或 fstream 对象内部维护的一个变量,文件刚打开时,文件写指针指向的是文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 write() 方法写入 n 个字节,写指针指向的位置就向后移动 n 个字节。

下面的程序演示了如何将学生信息以二进制形式写入文件:

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
public:
    char szName[20];
    int age;
};
int main()
{
    CStudent s;
    ofstream outFile("students.dat", ios::out | ios::binary);
    while (cin >> s.szName >> s.age)
        outFile.write((char*)&s, sizeof(s));
    outFile.close();
    return 0;
}

输入:

Tom 60
Jack 80
Jane 40
^Z

其中,表示输出换行符,^Z 表示输入Ctrl+Z组合键结束输入。

执行程序后,会自动生成一个 students.dat 文件,其内部存有 72 字节的数据,如果用“记事本”打开此文件,可能看到如下乱码:

Tom 烫烫烫烫烫烫烫烫<   Jack 烫烫烫烫烫烫烫蘌   Jane 烫烫烫烫烫烫烫?

值得一提的是,程序中第 13 行指定文件的打开模式为 ios::out | ios::binary,即以二进制写模式打开。在 Windows平台中,以二进制模式打开文件是非常有必要的,否则可能出错。

另外,第 15 行将 s 对象写入文件。s 的地址就是要写入文件的内存缓冲区的地址,但是 &s 不是 char * 类型,因此要进行强制类型转换;第 16 行,文件使用完毕一定要关闭,否则程序结束后文件的内容可能不完整。

C++ istream::read()方法读文件

ifstream 和 fstream 的 read() 方法实际上继承自 istream 类,其功能正好和 write() 方法相反,即从文件中读取 count 个字节的数据。该方法的语法格式如下:

istream & read(char* buffer, int count);

其中,buffer 用于指定读取字节的起始位置,count 指定读取字节的个数。同样,该方法也会返回一个调用该方法的对象的引用。

和 write() 方法类似,read() 方法从文件读指针指向的位置开始读取若干字节。所谓文件读指针,可以理解为是 ifstream 或 fstream 对象内部维护的一个变量。文件刚打开时,文件读指针指向文件的开头(如果以 ios::app 方式打开,则指向文件末尾),用 read() 方法读取 n 个字节,读指针指向的位置就向后移动 n 个字节。因此,打开一个文件后连续调用 read() 方法,就能将整个文件的内容读取出来。

通过执行 write() 方法的示例程序,我们将 3 个学生的信息存储到了 students.dat 文件中,下面程序演示了如何使用 read() 方法将它们读取出来:

#include <iostream>
#include <fstream>
using namespace std;
class CStudent
{
public:
    char szName[20];
    int age;
};
int main()
{
    CStudent s;
    ifstream inFile("students.dat",ios::in|ios::binary); //二进制读方式打开
    if(!inFile) {
        cout << "error" <<endl;
        return 0;
    }
    while(inFile.read((char *)&s, sizeof(s))) { //一直读到文件结束
        cout << s.szName << " " << s.age << endl;
    }
    inFile.close();
    return 0;
}

程序的输出结果是:

Tom 60
Jack 80
Jane 40

注意,程序中第 18 行直接将 read() 方法作为 while 循环的判断条件,这意味着,read() 方法会一直读取到文件的末尾,将所有字节全部读取完毕,while 循环才会终止。

另外,在使用 read() 方法的同时,如果想知道一共成功读取了多少个字节(读到文件尾时,未必能读取 count 个字节),可以在 read() 方法执行后立即调用文件流对象的 gcount() 成员方法,其返回值就是最近一次 read() 方法成功读取的字节数。感兴趣的读者可自行尝试,这里不再做具体演示。

总结

到此这篇关于C++用read()和write()读写二进制文件的文章就介绍到这了,更多相关C++ read()和write()读写二进制文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解C++编程中对二进制文件的读写操作

    二进制文件不是以ASCII代码存放数据的,它将内存中数据存储形式不加转换地传送到磁盘文件,因此它又称为内存数据的映像文件.因为文件中的信息不是字符数据,而是字节中的二进制形式的信息,因此它又称为字节文件. 对二进制文件的操作也需要先打开文件,用完后要关闭文件.在打开时要用ios::binary指定为以二进制形式传送和存储.二进制文件除了可以作为输入文件或输出文件外,还可以是既能输入又能输出的文件.这是和ASCII文件不同的地方. 用成员函数read和write读写二进制文件 对二进制文件的读写主

  • C/C++中二进制文件&顺序读写详解及其作用介绍

    目录 概述 二进制 vs ASCII 二进制写入 ASCII 写入 read 和 write 读写二进制文件 案例一 案例二 概述 二进制文件不同于文本文件, 它可以用于任何类型的文件 (包括文本文件). 二进制 vs ASCII 对于数值数据, ASCII 形式与二进制形式不同. ASCII 文件直观, 便于阅读, 但一般占存储空间较多, 而且需要花时间转换. 二进制文件是计算机的内部形式, 节省空间且不需要转换, 但不能直观显示. 对于字符信息, 在内存中是以 ASCII 代码形式存放, 无

  • C/C++读写文本文件、二进制文件的方法

    一:目的 掌握C语言文本文件读写方式: 掌握C语言二进制文件读写方式: 掌握CPP文本文件读写方式: 掌握CPP二进制文件读写方式: 二:C语言文本文件读写 1. 文本文件写入 //采用C模式对Txt进行写出 void TxtWrite_Cmode() { //准备数据 int index[50] ; double x_pos[50], y_pos[50]; for(int i = 0; i < 50; i ++ ) { index[i] = i; x_pos[i] = rand()%1000

  • C++用read()和write()读写二进制文件的超详细教程

    目录 前言 C++ ostream::write()方法写文件 C++ istream::read()方法读文件 总结 前言 通过前一节的学习,读者了解了以文本形式读写文件和以二进制形式读写文件的区别,并掌握了用重载的 >> 和 << 运算符实现以文本形式读写文件.在此基础上,本节继续讲解如何以二进制形式读写文件. 不过介绍具体的实现方法前,先给读者介绍一下相比以文本形式读写文件,以二进制形式读写文件有哪些好处? 举个例子,现在要做一个学籍管理程序,其中一个重要的工作就是记录学生的

  • 用VBS读写二进制文件的另一种方法分享

    之前写的那篇给出的方法虽然不错,但是当文件过大时(其实很小,也就几M),对应的数组也会很大,然后会出现运行时错误,提示内存耗尽,为此我郁闷了好久. 最近在博客的流量记录中发现百度关键字"一些很恶作剧的vbs程序"(看来现在的年轻人很喜欢玩这口),于是打开久违的百度搜索了一下,发现出现在第三.出现在第二的是百度HI,上面也是一个恶作剧程序,而且还是加密的.我尝试着解密,却发现这个加密似乎比前几天解密的那个病毒更变态,未果. 虽然我没有把那个程序解密出来(如果哪位真正的高手会,麻烦指点一下

  • python读写二进制文件的方法

    本文实例讲述了python读写二进制文件的方法.分享给大家供大家参考.具体如下: 初学python,现在要读一个二进制文件,查找doc只发现 file提供了一个read和write函数,而且读写的都是字符串,如果只是读写char等一个字节的还行,要想读写如int,double等多字节数 据就不方便了.在网上查到一篇贴子,使用struct模块里面的pack和unpack函数进行读写.下面就自己写代码验证一下. >>> from struct import * >>> fi

  • jscript读写二进制文件的方法

    本文实例讲述了jscript读写二进制文件的方法.分享给大家供大家参考.具体实现方法如下: var bin = new Array(256); for(var i=0;i<256;i++){ bin[i]=String.fromCharCode(i); } function TestWrite(){ var Stream = new ActiveXObject("ADODB.Stream"); var adTypeBinary=1,adTypeText=2; Stream.Typ

  • 利用二进制文件安装etcd的教程详解

    etcd组件作为一个高可用强一致性的服务发现存储仓库. etcd作为一个受到ZooKeeper与doozer启发而催生的项目,除了拥有与之类似的功能外,更专注于以下四点. 简单:基于HTTP+JSON的API让你用curl就可以轻松使用. 安全:可选SSL客户认证机制. 快速:每个实例每秒支持一千次写操作. 可信:使用Raft算法充分实现了分布式. 场景一:服务发现(Service Discovery)一个强一致性.高可用的服务存储目录.基于Raft算法的etcd天生就是这样一个强一致性高可用的

  • java读写二进制文件的解决方法

    接口:Writerable 复制代码 代码如下: package com.geoway.pad.common; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public interface Writerable {        //write         public void  write(DataOutput data) throws IOException;     

  • python读写csv文件方法详细总结

    python提供了大量的库,可以非常方便的进行各种操作,现在把python中实现读写csv文件的方法使用程序的方式呈现出来. 在编写python程序的时候需要csv模块或者pandas模块,其中csv模块使不需要重新下载安装的,pandas模块需要按照对应的 python版本安装. 在python2环境下安装pandas的方式是: sudo pip install pandas 在python3环境下安装pandas的方式是: sudo pip3 install pandas 1.使用csv读写

  • C#读写xml文件方法总结(超详细!)

    目录 C#写入xml文件 1.XmlDocument 2.DataSet对象里的值来生成XML文件 3.利用XmlSerializer来将类的属性值转换为XML文件的元素值. 示例:写入xml 1.创建xml文档 2 .增加节点 3 .修改节点: 4 .删除节点 c#读取xml文件 总结 C#写入xml文件 1.XmlDocument 1.我认为是最原始,最基本的一种:利用XmlDocument向一个XML文件里写节点,然后再利用XmlDocument保存文件.首先加载要写入的XML文件,但是如

  • mysql8.0.23 linux(centos7)安装完整超详细教程

    上篇文章给大家介绍了MySQL 8.0.23 主要更新一览(新特征解读) ,感兴趣的朋友点击查看吧! 最新版windows mysql-8.0.23-winx64,点击下载 mysql8.0.23 linux(centos7)安装教程(附:配置外网连接用户授权 与 不区分大小写配置) (博主在这里叨叨几句,稍后进入正题.在使用开发过程中,有时候数据库结合使用,会成倍提高程序效率) 什么是关系型数据库? 常见的关系型数据库: (其实博主也只使用过 MySQL Oracle sqlServer) O

  • mysql-canal-rabbitmq 安装部署超详细教程

    原文 1.1. 开启 MySQL 的 binlog 日志 1.修改 my.cnf 或 my.ini(windows), 添加配置项: # binlog 日志存放路径 log-bin=D:\env\mysql-5.7.28-winx64\binlog # 日志中记录每一行数据被修改的形式 binlog-format=ROW # 当前机器的服务 ID, 如果为集群时不能重复 server_id=1 2.重启 mysql 服务后, 查看配置变量是否生效: mysql> show variables l

随机推荐