Qt实现GUI的二进制文件读写操作(源码分析+工程打包+测试例子)

本人小菜一枚,上周老大要写一个Qt软件
需求:实现二进制文件读写,写入Version(如intx型 104)、累加校验和(int型sum)、字符串(“deadbeaf”)

其实在二进制的read上,是不做要求的,我目前用的是QTextStream读取的文本文件,并非QDataStream读取的二进制文件,所以这点说明下。

源码+可执行文件+测试.bin文件 一并打包上传 资源

实现的环境是 Ubuntu 14.04 32位,64可能直接运行可执行文件出错,需要你重新编译后执行

学习是和一个豆子的大神学习Qt的,目前才看了20个不到,一起加油!豆哥博客

mainwindow.h头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QTextEdit;
class QLineEdit;
class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private: //Action
    QAction   *openAction;
    QAction   *saveAction;
    QTextEdit *textEdit;

private:  //变量
    QLineEdit *Version;

private slots: //槽
    void openFile();
    void saveFile();
    int CKS();

};

#endif // MAINWINDOW_H

main.cpp

#include <QApplication>
#include "mainwindow.h"
#include "QIODevice"
#include "QFile"
#include "QFileInfo"
#include "QDebug"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.cpp

#include <QtGui>
#include <QtWidgets>
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QWidget *w = new QWidget(this); //控件对象
    this->setCentralWidget(w);

    Version = new QLineEdit(w); //单行文本输入域 version对象
    Version->setPlaceholderText("Version");

    textEdit = new QTextEdit(this);   //创建文本窗口域


    QGridLayout *grid = new QGridLayout(w);//网格布局对象
    grid->addWidget(Version, 0, 0, 0);
    grid->addWidget(textEdit,1, 0, 0);

    openAction = new QAction(QIcon(":/images/file-open"), tr("&Open..."), this);
    openAction->setShortcuts(QKeySequence::Open);
    openAction->setStatusTip(tr("Open an existing file"));
    connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
    //将openAction这个Action与MainWindow下的openFile()连在一起,只要触发了openAction控件,就openFile一下

    saveAction = new QAction(QIcon(":/images/file-save"), tr("&Save..."), this);
    saveAction->setShortcuts(QKeySequence::Save);
    saveAction->setStatusTip(tr("Save a new file"));
    connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);


    QMenu *file = menuBar()->addMenu(tr("&File"));
    file->addAction(openAction);//增加菜单栏控件
    file->addAction(saveAction);


    QToolBar *toolBar = addToolBar(tr("&File"));
    toolBar->addAction(openAction);//增加工具栏控件
    toolBar->addAction(saveAction);

    //布局
    QHBoxLayout* passwordEditLayout = new QHBoxLayout();//左右排列对象
    passwordEditLayout->addStretch();  //Username Password 平均分配布局
    passwordEditLayout->setSpacing(0);            //设置空间之间的距离
    passwordEditLayout->setContentsMargins(0, 0, 8, 0);//设置左侧、顶部、右侧和底部边距,以便在布局周围使用。
    Version->setLayout(passwordEditLayout);  //对左右排列对象  进行布局

    //setCentralWidget(textEdit);

}

MainWindow::~MainWindow()
{
}
//--------------------采用Ascii码 计算textEdit文本框内的 Ascii编码累加和----------------------------//
int MainWindow::CKS()
{
    int len;
    QString str;
    int sum = 0;
    str = textEdit->toPlainText();   //QLineEdit的QTextEdit 用toPlainText()获取文本框内的字符串 赋给 QString的str
    len = str.length()-1;
    for(int i=0; i<len; i++)
    {
        QChar t = str.at(i);  //QString的str 用at() 获取存入的字符 赋给QChar型的t
        int num = t.toLatin1();//QChar型的t 用toLatin1()转成Ascii码 赋给 int的 num
        sum = sum + num;
    }
    return sum;
}

void MainWindow::openFile()
{
    QString buf;
    QString path = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Text Files(*.txt *.bin)"));
    if(!path.isEmpty())
    {
        QFile file(path);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Truncate))
        {
            QMessageBox::warning(this, tr("Read File"), tr("Cannot open file:\n%1").arg(path));
            return;
        }
//        QDataStream in(&file);                 //这里想用QDataStream来进行二进制读取,但是好像有bug,
//        while(!in.atEnd()){                    //运行会出现“The program has unexpectedly finished.”的报错,是不是256不对?
//            in.readRawData((char *)&buf, 256); //记得有篇博客说,QDataStream的read必须读的是QDataStream的写入的内容,不然会不对应,
//            //qDebug() <<  buf;                //而且还需要  in.setVersion(QDataStream::Qt_4_7);用你自己写入的版本读取
//        }
//        textEdit->setText(buf);
        QTextStream in(&file);  //这里使用的QTextStream流读取的,其实并不是二进制的读取
        textEdit->setText(in.readAll());
        file.close();
    }
    else
    {
        QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));
    }
}

void MainWindow::saveFile()
{
    int sum = 0;
    bool ok;
    int dec_version = 0;
    QString path = QFileDialog::getSaveFileName(this, tr("Save File"), ".", tr("Text Files(*.txt *.bin)"));
    if(!path.isEmpty())
    {
        QFile file(path);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
        {
            QMessageBox::warning(this, tr("Write File"), tr("Cannot open file:\n%1").arg(path));
            return;
        }

        QDataStream out(&file);
        dec_version = Version->text().toInt(0,10);
        out.writeRawData((char*)&dec_version, 4);//writeRawData 将原始内存写入file中,可避免QDataSream默认写入时增加的len(字节长度)

        sum = CKS(); //写入版本号之后,再利用Ascii码计算累加校验和
        out.writeRawData((char*)&sum,4);
        qDebug() << "sum:" << sum;  //打印int型的sum值

        char data[8];
        memset(data,0,8*sizeof(char));
        char* p = "deadbeaf";
        strcpy(data,p);
        out.writeRawData(data,8);

//知识点1
//        QDataStream out_1(&file,QIODevice::ReadWrite); //我这里的QDataStream默认是小端,如果要想写入大端,用这里的API
//        out_1.setByteOrder(QDataStream::LittleEndian);
//知识点2
//        out << textEdit->toPlainText();                                      //单行文本输入域 version内容
//        dec_version = Version->text().toInt(0,10);                           //再转换成10进制的int型
//        QString str=QString("%1").arg(dec_version,8,16,QLatin1Char('0'));    //这里是多此一举了,将int型转为字符串,再转为int型
//        hex_version=str.toInt(&ok,16);                                       //和直接输出 hex >> dec_version一个效果
//        out << hex << dec_version;
//        out << hex << sum;                                                   //一直都在.bin文件中写入5个字节,总有个01在4字节的sum前面
//知识点2
        QString str=QString("%1").arg(sum,8,16,QLatin1Char('0'));
        //QString::arg ( int a, int fieldWidth = 0, int base = 10, const QChar & fillChar = QLatin1Char( ' ' ) )
        //a:输入的值,fieldWidth:字符宽度,base:进制,fillChar:填充字符
        sum=str.toInt(&ok,16);  //将str转成16进制的数sum,但是这里16进制的sum还是以文本写入的file,并非二进制写入file
        qDebug() << str;     //打印str的内容
        qDebug() <<"sum(int): "<<sum;
        file.close();
    }
    else
    {
        QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));//弹出提示框
    }
}

红色:Version 104
绿色:Sum 6401707   0061AEA5
灰色:deadbeaf

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值