当前位置: 首页 > news >正文

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

 文章的目的为了记录使用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.dtcms.com/a/342072.html

相关文章:

  • Elasticsearch官方文档学习-未完待续
  • java项目:如何优化JVM参数?
  • 【深入理解 Linux 网络】收包原理与内核实现(下) 从 TCP 传输层到应用
  • 遥感机器学习入门实战教程|Sklearn案例⑤:集成学习方法全览
  • ES_flattened
  • Nacos部署微服务
  • Python机器学习入门:用scikit-learn构建你的第一个预测模型
  • 安装nvtop编译报错:fatal error: linux/kcmp.h: No such file or directory
  • 亚远景科技助力力邦合信通过ASPICE CL2评估
  • 今日科技焦点 | A股科技芯片受追捧,美股科技股承压——技术赛道的资本与市场博弈
  • 云计算下数据隐私保护系统的设计与实现(LW+源码+讲解+部署)
  • 2025高性能氢气传感器领域的创新引领者:杭州德克西智能科技有限公司
  • 云计算学习笔记——用户和组的管理、周期性任务篇
  • ECCV 2020 | 动态图像在3D MRI图像阿尔茨海默病分类中的应用
  • Wireshark USRP联合波形捕获
  • 软件测试体系建设要怎么做
  • 手写MyBatis第28弹:告别代理,直击本质:手写MyBatis SqlSession的增删改查奥秘
  • 深入解析HashMap的存储机制:扰动函数、哈希计算与索引定位
  • Halcon那些事:Halcon非常核心的1个概念reduce_domain算子的理解和1个详细的使用示例
  • Nginx缓存配置指南:使用proxy_cache为动态网站提速10倍
  • WPF中UI线程频繁操作造成卡顿的处理
  • Ingress控制器深度解析:Nginx与Traefik实战指南
  • 【DICOM HL7】DICOM hl7协议的哪个字段对应操作者,操作者ID?
  • C++析构函数
  • Linux下Docker版本升级保姆攻略
  • 结合 Flutter 和 Rust 的跨平台开发方案
  • 微软Auzre云的技术支持运营模式是什么
  • Flutter - UI布局
  • Android APP防止应用被动态调试
  • 大数据毕业设计选题推荐-基于大数据的北京气象站数据可视化分析系统-Hadoop-Spark-数据可视化-BigData