C++ 读写二进制文件

2023-11-17

描述

C++来读取二进制文件
二进制文件的格式可以多种多样,比如dat、index等,还可以是自行定义的格式

C++来写二进制文件

一、读二进制文件

结构体定义及头文件

#include <stdio.h>
#include <string.h> 
#include <stdlib.h>
#include <iostream>

struct index_data {
    uint16_t  id1;
    uint8_t   id2;
};
index_data my_index;

打开二进制文件

FILE * fp;
if((fp=fopen("../1.dat","rb"))==NULL) //rb代表按照二进制的方式进行读
{
  printf("cant open the file");
  exit(0);
}

读取二进制文件

while(fread(&my_index, sizeof(index_data), 1, fp) == 1)   //如果读到数据,就显示;否则退出
{
	std::cout<<std::hex<<int(my_index.id)<<std::endl; // 十六进制显示
	std::cout<<std::dec<<int(my_index.id)<<std::endl; // 十进制显示
}

使读取指针跳到指定位置

比如,跳100个字节

fseek(fp, 100, 0);

关闭文件

注意,每一次再fopen同一文件前,一定要先fclose一下

fclose(fp);

代码解释

  1. 首先要知道你要读取的二进制文件,其存放的格式是什么
  2. 根据存放的数据格式,你来定义该数据格式的变量
    例如,你的数据存放了一个uint8_t格式的id1和一个uint16_t格式的id2
    那么你就应该定义这样的变量
  3. 再通过以上代码中while的语句,从二进制文件中,持续读出你想要的数据

几个重要细节

数据占位

std::cout<<"int: "<<sizeof(int)<<std::endl;
std::cout<<"char: "<<sizeof(char)<<std::endl;
std::cout<<"float: "<<sizeof(float)<<std::endl;
std::cout<<"double: "<<sizeof(double)<<std::endl;
std::cout<<"uint8_t: "<<sizeof(uint8_t)<<std::endl;
std::cout<<"uint16_t: "<<sizeof(uint16_t)<<std::endl;
std::cout<<"uint32_t: "<<sizeof(uint32_t)<<std::endl;
int: 4
char: 1
float: 4
double: 8
uint8_t: 1
uint16_t: 2
uint32_t: 4

几种常见数据所占的字节数

数据对齐

#pragma pack(1)

在这句代码后面的数据定义,会按照1个字节来对齐数据

举例子

  • 如果不加#pragma pack(1)这句话,代码会自动对齐字节

     struct data{
         char a;
         int n;
     };
     std::cout<<sizeof(data)<<std::endl;
    

    你会得到输出结果为8,因为char为1,int为4,而data的数据占位在char型变量a后面会留3个空字节,char1个字节+3个空字节+int4个空字节=8个字节

  • 而加上#pragma pack(1),你会发现输出结果为5
    因为你预定义了,数据按1字节来对齐

  • 因此同样的数据格式,data1的size为8个字节,而data2的size为5个字节

    struct data1{
        char a;
        int n;
    };
    #pragma pack(1)
    struct data2{
        char a;
        int n;
    };
    

uint16_t的读取问题

uint16_t占2个字节,因此它存在数据高位和低位

uint16_t id = 0x3FC6;
uint8_t low = id & 0xFF;
uint8_t high = (id >> 8) & 0xFF;
std::cout<<std::hex<<int(high)<<" "<<int(low)<<std::endl; 
// 输出结果:3f c6
std::cout<<std::hex<<int(high)<<" "<<int(low)<<std::endl; 
// 输出结果:63 198
std::cout<<std::dec<<a<<std::endl;
// 输出结果:16326

解释一下
3f、 c6:原本的数据高位和数据低位
63 、198: 3f、 c6由十六进制转成十进制
16326:id的值3FC6,由十六进制转成十进制的结果

如果输出代码中不加int(),high的输出会是“?”
因为63在二进制中代表了“?”

 uint8_t xxx = 43;
 std::cout<<xxx<<std::endl; // 输出结果为43代表的“+”

二、写二进制文件

头文件

#include <iostream>
#include <fstream>

假设我们有结构体需要写

struct A {
	int a,
	int b;
};
struct B {
	std::string x,
	std::string y;
};

调用

std::string filename = "../1.dat" ;
std::ofstream fout;
fout.open(filename, std::ios::out| std::ios::app | std::ios::binary);
if (fout.is_open() == false)
{
    std::cout << "打开文件" << filename << "失败。"<<std::endl;  
    return 0;
}
A data_1;
B data_2;
fout.write((const char*)&data_1, sizeof(A));
fout.write((const char*)&data_2, sizeof(B));
std::cout<<"sizeof(A):"<<sizeof(A)
    <<" sizeof(B):"<<sizeof(B)<<std::endl;
fout.close();

命令

在终端查看二进制dat文件

hexdump 1.dat 

比较两个二进制文件是否相同

cmp 1.dat 2.dat
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 读写二进制文件 的相关文章

随机推荐

  • Python教程:类的继承——深入理解继承的概念和用法

    Python教程 类的继承 深入理解继承的概念和用法 类的继承是面向对象编程中的重要概念 它允许我们定义一个新的类 并从现有的类中继承属性和方法 这种继承关系可以让我们在代码中实现代码重用 提高代码的可维护性和可扩展性 在本文中 我们将深入
  • k8s非高可用环境搭建

    k8s非高可用环境搭建 文章目录 k8s非高可用环境搭建 环境准备 集群信息 1 节点规划 2 修改hostname 3 添加hosts解析 4 调整系统配置 5 安装docker 部署kubernetes 1 安装kubernetes k
  • Python 一篇入门

    目录 Python 的简介与特点 Python支持多种编程风格 解释运行 跨平台 可扩展强 可嵌入 丰富的库 Python版本选择 Python开发环境搭建 认识Python解释器 快速入门 变量和赋值 动态类型 变量命名规则 认识 数字
  • Android DataStore 使用详解

    转载请标明出处 http blog csdn net zhaoyanjun6 article details 127358235 本文出自 赵彦军的博客 文章目录 概述 使用 DataStore 本地数据 查看DataStore 文件 Ke
  • Eclipse中JUnit的安装及初始使用

    JUnit的下载 安装 1 下载 http www junit org JUnit软件包 版本很多 可以自行选择 2 在eclipse中添加junit jar包 打开eclipse gt 菜单栏点击project gt properties
  • ubuntu pip intall出现“设备上没有空间”的解决办法

    原因 空间问题呗 东西太多了 tmp盘不够大 pip install的时候文件包会预先下载到tmp盘 步骤1 在home目录下新建一个tmp文件夹 用来取代系统根目录的tmp文件夹 步骤2 设置环境变量TMPDIR export TMPDI
  • [LeetCode-02]-Add Two Numbers-性能极好

    文章目录 题目相关 Solution 1 错误的解法 2 正确解法 3 几个用例 后记 每周完成一个ARTS Algorithm Review Tip Share ARTS Algorithm 每周至少做一个 leetcode 的算法题 R
  • 强化学习打卡班第四五章

    强化学习打卡班第四五章 第四章 Policy Gradient梯度策略 例子 贝叶斯公式补充 奖励函数 reward function 最大化方法 梯度上升 PPO算法 从 On policy 到 Off policy 第四章 Policy
  • Linux 使用wget 命令下载JDK的方法

    Oracle官网上下载jdk 需要点击accept licence的才能下载 使用下面的命令 直接可以下载 wget no check certificate no cookies header Cookie oraclelicense a
  • DeBlurGANv2图像去模糊 训练自己的数据集

    之前在有位博主的DeblurGANv2教程的页面下留了言 很多小伙伴来私信我 config yaml怎么调参数 predict py和train py需要怎么修改 之前只跑了predict 有些问题也没办法解答 最近自己跑了一下train
  • MTU 和 MSS 区别

    MTU Maximum Transmit Unit 最大传输单元 即物理接口 数据链路层 提供给其上层 通常是IP层 最大一次传输数据的大小 以普遍使用的以太网接口为例 缺省MTU 1500 Byte 这是以太网接口对IP层的约束 如果IP
  • HPE Microserver GEN10升级BIOS

    到手的机子BIOS版本还是ZA10A290 非常有必要升级 便从HPE官网下载了最新的版本 ZA10A360 选择UEFI Shell方式更新 官网下载地址 https support hpe com hpesc public km pro
  • Cutter - Web视频剪辑工具原理浅析

    大厂技术 坚持周更 精选好文 最近一直在开发 web视频剪辑工具 cutter 这个工具可以方便老师们编辑拍摄好的视频 这是一个挺有意思的项目 预计分多章和大家分享介绍 本期主要介绍下其大体流程 方便大家对其原理有一个简单认知 Cutter
  • Docker安全设置

    Docker安全 Linux内核的命名空间机制提供的容器隔离安全 Linux控制组机制对容器资源的控制能力安全 Linux内核的能力机制所带来的操作权限安全 Docker程序 特别是服务端 本身的抗攻击性 其他安全增强机制对容器安全性的影响
  • elementui不生效

    1 element依赖vue 引入element js之前要引入vue js 2 element无法脱离Vue使用 html中必须new Vue el app 挂载上去
  • C语言函数大全--f开头的函数(下)

    f开头的函数 下 21 floor floorf floorl 21 1 函数说明 21 2 演示示例 21 3 运行结果 22 flushall 22 1 函数说明 22 2 演示示例 22 3 运行结果 23 fma fmaf fmal
  • php发送请求写请求头,PHP发送请求头和接收打印请求头

    一 发送请求头 发送地址 url http 127 0 0 1 2 php 请求头内容 headers array Authorization basic suibianzhi basic 使用curl发送 ch curl init url
  • 计算机缺失VCRUNTIME140.dll怎么办,那个修复方法可以解决

    计算机提示缺失VCRUNTIME140 dll怎么办 无法启动运行软件程序 如photoshop pr ae等等都是无法启动 打开电脑就报错 由于找不到VCRUNTIME140 dll 无法继续执行此代码 让我们先来了解一下VCRUNTIM
  • Gitee初练 --- 问题合集(一)

    Gitee 一 Windows找不到gpedit msc请确定文件名是否正确的提示 二 windows 10 凭据无法保存 三 解决 git pull push 每次都要输入用户名密码的问题 一 Windows找不到gpedit msc请确
  • C++ 读写二进制文件

    描述 C 来读取二进制文件 二进制文件的格式可以多种多样 比如dat index等 还可以是自行定义的格式 C 来写二进制文件 一 读二进制文件 结构体定义及头文件 include