開源 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.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> 中,…