文章的目的为了记录使用C++ 进行QT Widget 开发学习的经历。临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

  相关链接:

开源 C++ QT Widget 开发(一)工程文件结构-CSDN博客

开源 C++ QT Widget 开发(二)基本控件应用-CSDN博客

开源 C++ QT Widget 开发(三)图表--波形显示器-CSDN博客

开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑-CSDN博客

 
推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

本章主要内容:二进制文件查看和编辑工具。

二进制文件的读写用途主要体现在需要高效存储和访问非文本数据的场景,例如:

数据存储优化

二进制文件直接以内存中的数据格式存储,无需进行文本编码/解码转换,可显著减少存储空间并提升读写效率。例如操作系统、编译器或图形处理软件中的可执行文件、图片和视频文件常采用二进制存储。 ‌

随机访问需求

二进制文件支持随机读写操作,可直接定位到文件中的特定位置进行数据存取,适用于需要频繁读写或修改文件的场景(如日志记录、实时数据处理)。

跨平台兼容性

二进制文件格式与硬件平台关联较小,通过约定统一的字节顺序和协议,可实现跨平台数据交换,常见于嵌入式系统、游戏开发等领域。

一、内容介绍 ‌

这是一个简单的二进制文件编辑器,具有:

文件打开和保存功能

二进制数据的十六进制显示

基本的编辑能力

类似hex编辑器的界面布局

工程比较简单,只需要修改,mainwindow.h 和 mainwindow.cpp 如下图。

二、代码分析

核心功能方法
2.1  文件打开功能 (on_btnOpen_clicked)

使用QFileDialog选择文件

读取二进制文件内容

格式化数据显示在文本框中

2.2  文件保存功能 (on_btnClose_clicked)

检查是否有打开的文件

解析文本框中的格式化数据

写回二进制文件

2.3  二进制文件读写

readBinaryFile:读取整个二进制文件

writeBinaryFile:写入二进制数据到文件

2.4  数据格式化与解析

formatBinaryData:将二进制数据格式化为十六进制查看格式

每行显示16字节

显示偏移地址

8字节一组,中间有间隔

使用大写十六进制表示

parseBinaryData:将格式化的文本解析回二进制数据

跳过空行和地址部分

提取十六进制字节并转换

三、所有源码

3.1  mainwindow.h源码

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_btnOpen_clicked();void on_btnClose_clicked();private:Ui::MainWindow *ui;QString currentFilePath;QByteArray readBinaryFile(const QString &filePath);bool writeBinaryFile(const QString &filePath, const QByteArray &data);QString formatBinaryData(const QByteArray &data);QByteArray parseBinaryData(const QString &text);
};#endif // MAINWINDOW_H

3.2  mainwindow.cpp源码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextStream>
#include <QRegularExpression>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);currentFilePath = "";
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_btnOpen_clicked()
{QString filePath = QFileDialog::getOpenFileName(this, "打开二进制文件", "", "所有文件 (*.*)");if (filePath.isEmpty()) {return;}currentFilePath = filePath;QByteArray fileData = readBinaryFile(filePath);if (!fileData.isEmpty()) {QString formattedText = formatBinaryData(fileData);ui->txtFile->setPlainText(formattedText);}
}void MainWindow::on_btnClose_clicked()
{if (currentFilePath.isEmpty()) {QMessageBox::warning(this, "警告", "请先打开一个文件");return;}QString textContent = ui->txtFile->toPlainText();QByteArray binaryData = parseBinaryData(textContent);if (writeBinaryFile(currentFilePath, binaryData)) {QMessageBox::information(this, "成功", "文件保存成功");} else {QMessageBox::critical(this, "错误", "文件保存失败");}
}QByteArray MainWindow::readBinaryFile(const QString &filePath)
{QFile file(filePath);if (!file.open(QIODevice::ReadOnly)) {QMessageBox::critical(this, "错误", "无法打开文件: " + file.errorString());return QByteArray();}QByteArray data = file.readAll();file.close();return data;
}bool MainWindow::writeBinaryFile(const QString &filePath, const QByteArray &data)
{QFile file(filePath);if (!file.open(QIODevice::WriteOnly)) {QMessageBox::critical(this, "错误", "无法写入文件: " + file.errorString());return false;}qint64 bytesWritten = file.write(data);file.close();return bytesWritten == data.size();
}QString MainWindow::formatBinaryData(const QByteArray &data)
{QString result;QTextStream stream(&result);for (int i = 0; i < data.size(); i += 16) {// 写入地址(4字节十六进制,前导0)加上冒号和4个空格stream << QString("%1").arg(i, 4, 16, QLatin1Char('0')).toUpper() << ":    ";// 写入前8个字节的数据for (int j = 0; j < 8; j++) {if (i + j < data.size()) {unsigned char byte = static_cast<unsigned char>(data[i + j]);stream << QString("%1").arg(byte, 2, 16, QLatin1Char('0')).toUpper() << " ";} else {stream << "   "; // 空白填充}}// 在前8个字节和后8个字节之间添加2个空格的间隔stream << "  ";// 写入后8个字节的数据for (int j = 8; j < 16; j++) {if (i + j < data.size()) {unsigned char byte = static_cast<unsigned char>(data[i + j]);stream << QString("%1").arg(byte, 2, 16, QLatin1Char('0')).toUpper() << " ";} else {stream << "   "; // 空白填充}}stream << "\n";}return result;
}
QByteArray MainWindow::parseBinaryData(const QString &text)
{QByteArray result;QStringList lines = text.split('\n');for (const QString &line : lines) {// 跳过空行if (line.trimmed().isEmpty()) {continue;}// 查找冒号的位置来分割地址和数据部分int colonIndex = line.indexOf(':');if (colonIndex == -1) {continue; // 如果没有冒号,跳过这一行}// 提取数据部分(冒号后的内容)QString dataLine = line.mid(colonIndex + 1).trimmed();// 分割空格分隔的十六进制字节QStringList hexBytes = dataLine.split(' ', QString::SkipEmptyParts);for (const QString &hexByte : hexBytes) {if (hexByte.length() == 2) {bool ok;char byte = static_cast<char>(hexByte.toInt(&ok, 16));if (ok) {result.append(byte);}}}}return result;
}

四、演示效果

打开二进制文件

显示二进制文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93920.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93920.shtml
英文地址,请注明出处:http://en.pswp.cn/web/93920.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【密码学实战】X86、ARM、RISC-V 全量指令集与密码加速技术全景解析

前言 CPU 指令集是硬件与软件交互的核心桥梁&#xff0c;其设计直接决定计算系统的性能边界与应用场景。在数字化时代&#xff0c;信息安全依赖密码算法的高效实现&#xff0c;而指令集扩展则成为密码加速的 “隐形引擎”—— 从服务器端的高吞吐量加密&#xff0c;到移动端的…

2025-08-21 Python进阶2——数据结构

文章目录1 列表&#xff08;List&#xff09;1.1 列表常用方法1.2 列表的特殊用途1.2.1 实现堆栈&#xff08;后进先出&#xff09;1.2.2 实现队列&#xff08;先进先出&#xff09;1.3 列表推导式1.4 嵌套列表推导式2 del 语句3 元组&#xff08;Tuple&#xff09;4 集合&…

告别手工编写测试脚本!Claude+Playwright MCP快速生成自动化测试脚本

在进行自动化测试时&#xff0c;前端页面因为频繁迭代UI 结构常有变动&#xff0c;这往往使得自动化测试的脚本往往“写得快、废得也快”&#xff0c;维护成本极高。在大模型之前大家往往都会使用录制类工具&#xff0c;但录制类工具生成的代码灵活性较差、定位方式不太合理只能…

一款更适合 SpringBoot 的API文档新选择(Spring Boot 应用 API 文档)

SpringDoc&#xff1a;Spring Boot 应用 API 文档生成的现代化解决方案 概述 SpringDoc 是一个专为 Spring Boot 应用设计的开源库&#xff0c;能够自动生成符合 OpenAPI 3 规范的 API 文档。它通过扫描项目中的控制器、方法注解及相关配置&#xff0c;动态生成 JSON/YAML/HTML…

文献阅读 250821-When and where soil dryness matters to ecosystem photosynthesis

When and where soil dryness matters to ecosystem photosynthesis 来自 <When and where soil dryness matters to ecosystem photosynthesis | Nature Plants> ## Abstract: Background: Projected increases in the intensity and frequency of droughts in the twen…

React学习(九)

目录&#xff1a;1.react-进阶-antd-新增2.react-进阶-antd-删除选中1.react-进阶-antd-新增新增代码&#xff0c;跟需改的代码类似&#xff0c;直接copy修改组件代码进行修改userEffect可以先带着&#xff0c;没啥用A6组件用到的函数跟修改的也类似&#xff1a;这个useEffect函…

零基础从头教学Linux(Day 17)

三层交换机一、三层交换机的配置1.关于如何配置三层交换机&#xff0c;首先我们应该先创建VLANSwitch>en Switch#vlan database % Warning: It is recommended to configure VLAN from config mode,as VLAN database mode is being deprecated. Please consult userdocument…

任务十四 推荐页面接口开发

一、接口准备 在对接qq音乐接口之前,首先要将之前的项目,一定要记得备份一份; 备份完成之后,首先要在vscode终端安装axios,这个是请求后端的工具,和之前的ajax一样,都是请求后端的工具。只不过axios更专业化,跟强大 至于qq音乐接口怎么获取,一般有两个途径,第一个是…

医疗AI与医院数据仓库的智能化升级:异构采集、精准评估与高效交互的融合方向(下)

核心功能创新详解: 统一门户与角色化工作台: 统一入口: 用户通过单一URL登录,系统根据其角色和权限自动呈现专属工作台。 角色化工作台: 临床医生工作台: 首屏展示常用患者查询入口、快速统计(如“我的患者检验异常趋势”)、相关临床文献推荐、待处理任务(如报告审核)…

数据库面试常见问题

数据库 Delete Truncate Drop 区别 答:这三个操作都是针对数据库的表进行操作,都有删除表的功能,其中的区别在于: Delete:只将表中的数据进行删除,不删除定义不释放空间,是dml语句,需要提交事务,如果不想删除可以回滚。delete每次删除一行,并在事务日志中为所删除…

用nohup setsid绕过超时断连,稳定反弹Shell

在We渗透过程中&#xff0c;我们常常会利用目标系统的远程代码执行&#xff08;RCE&#xff09;漏洞进行反弹Shell。然而&#xff0c;由于Web服务器&#xff08;如PHP、Python后端&#xff09;的执行环境通常存在超时限制&#xff08;如max_execution_time或进程管理策略&#…

Java设计模式-模板方法模式

Java设计模式-模板方法模式 模式概述 模板方法模式简介 核心思想&#xff1a;定义一个操作中的算法骨架&#xff08;模板方法&#xff09;&#xff0c;将算法中某些步骤的具体实现延迟到子类中完成。子类可以在不改变算法整体结构的前提下&#xff0c;重定义这些步骤的行为&…

Centos7物理安装 Redis8.2.0

Centos7物理安装 Redis8.2.0一、准备依赖环境首先安装编译 Redis 所需的依赖&#xff1a;# CentOS/RHEL系统 yum install -y gcc gcc-c make wget 二、下载并编译 Redis 8.2.0# 1. 下载Redis 8.2.0源码包 wget https://download.redis.io/releases/redis-8.2.0.tar.gz# 2. 解压…

牛津大学xDeepMind 自然语言处理(3)

条件语言模型无条件语言模型 概率计算&#xff1a;通过链式法则分解为预测下一词概率&#xff08;将语言建模问题简化为建模给定前面词语历史的下一个词的概率&#xff09;基于循环神经网络的无条件语言模型&#xff1a;根据历史词语预测下一个词的概率条件语言模型 定义&#…

Vue2.x核心技术与实战(一)

目录 一、Vue2.x:快速上手+插值表达式+指令上 1.1 Vue快速上手 1.1.1 Vue概念 1.1.2 创建实例 1.1.3 插值表达式 { { }} 1.1.4 响应式特性 1.1.5 开发者工具 1.2 Vue指令 1.2.1 v-html 1.2.3 v-show / v-if v-show v-if 1.2.4 v-else / v-else-if 1.2.5 v-on v…

SCAU学习笔记 - 自科三面前端方向实战演示

本来是准备写完二面直接开始写算法三面的&#xff0c;maimai那个封面图我都做好了。但是可恶的出题人说要等我出完解析再针对性避开出题&#xff0c;所以swan决定把那个先搁置&#xff0c;本文我们先以2023年的自科三面前端方向题为例带各位快速入门前端三件套&#xff08;因为…

前后端联合实现文件上传,实现 SQL Server image 类型文件上传

1、前端 Vue3QualityFileInfoDialog.vue<script setup lang"ts" name"QualityFile"> ...... // 上传&#xff0c;防抖 const onUploadClick debounce(() > {// 模拟点击元素if (fileInputRef.value) {// 重置以允许重复选择相同文件fileInputRef…

使用安卓平板,通过USB数据线(而不是Wi-Fi)来控制电脑(版本1)

这是一个对延迟和稳定性要求很高的场景。 核心原理是&#xff1a;利用USB数据线&#xff0c;在手机和电脑之间创建一个高速的“虚拟网络连接”&#xff0c;然后在这个稳定的网络通道上运行远程控制软件。 方案1&#xff1a; 在完全没有无线网络&#xff08;Wi-Fi&#xff09;和…

linux报permission denied问题

linux报permission denied问题 一般是没有可执行权限&#xff0c;需要先添加执行权限 1. 确认文件权限 在你的项目目录下执行&#xff1a; ls -l ./folder你可能会看到类似&#xff1a; -rw-r--r-- 1 user user 1234 Aug 18 12:00 script.sh注意&#xff1a;这里缺少 x&#xf…

Vue深入组件:组件事件详解2

声明触发的事件 为了让组件的用法更清晰(作为文档),同时让 Vue 能区分事件与透传 attribute,推荐显式声明组件要触发的事件。根据组件是否使用 <script setup>,声明方式有所不同。 使用 <script setup> 时:defineEmits() 宏 在 <script setup> 中,…