qml實現文本二進制互轉工具

  • 下載

windows環境,文本二進制互轉工具下載:https://download.csdn.net/download/lewanhah01/11831813

  • 界面及功能

首先實現的界面效果如下:

二進制轉文本( img.bin -> img.bin.txt)

而文本轉二進制是上面的反操作。

  • 實現

首先是main入口函數(main.c)

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQuickControls2>
#include "file_convert.h"
#include <QVariant>

QObject *gObject;

void showMessage(QVariant value)
{
    gObject->setProperty("text", value);
}

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    //使用系統自帶style
    QQuickStyle::setStyle("Universal");
    QQmlApplicationEngine engine;

    //創建對象並設置,之後可以在qml中以“FILECONVERT”名稱使用
    FileConvert fileConvert;
    engine.rootContext()->setContextProperty("FILECONVERT",&fileConvert);
    

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    //設置全局變量,供C++調用qml成員
    QObject *root = engine.rootObjects().first();
    gObject = root->findChild<QObject *>("tipLabelObj");
    if (!gObject) { return -1;}

    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml是界面相關的代碼:

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.2

ApplicationWindow {
    visible: true
    width: 520
    height: 210
    title: qsTr("文本二進制互轉工具V0.1  作者:大樹([email protected])")

    property bool isTxt2Bin: true        //定義bool類型的屬性變量
                                         //true表示文本轉二進制,false表示二進制轉文本

    Rectangle {
        id: fileListShow
        anchors.left: parent.left
        anchors.leftMargin: 2
        anchors.top: parent.top
        anchors.topMargin: 2

        width: parent.width/3*2
        height: parent.height - 2
        border.width: 1
        border.color: "#363636"
        radius: 1

        //選中文件後,路徑/文件名顯示
        Text {
            width: parent.width - 5
            id: labels
            //text: "file:///C:/Users/Administrator/Desktop/kernel_data.bin.txt"
            wrapMode: Text.WrapAnywhere
            font.family: "宋體"
            font.pixelSize: 14
        }
    }

    Rectangle {
        id:controlArea
        anchors.left: fileListShow.right
        anchors.top: parent.top
        anchors.topMargin: 10
        width: parent.width/3 - 4
        height: parent.height - 2

        Button {
            id:openBtn
            height: 32
            width: parent.width - 20
            text:qsTr("選擇文件")
            anchors.top: parent.top
            anchors.margins: 5
            anchors.horizontalCenter: parent.horizontalCenter

            onClicked: {
                fds.open();    //打開文件對話選擇框
            }
        }

        Button {
            id:convertBtn
            height: 32
            width: parent.width - 20
            text:qsTr("開始轉換")
            anchors.top: openBtn.bottom
            anchors.margins: 5
            anchors.horizontalCenter: parent.horizontalCenter

            onClicked: {
                if(FILECONVERT.fileName == "") {
                    tipLabel.text = "未選擇轉換文件"
                }
                else {
                    if(isTxt2Bin)
                        FILECONVERT.doConvert(1); //調用c++方法,傳入參數1,表示文本轉二進制
                    else
                        FILECONVERT.doConvert(2); //調用c++方法,傳入參數2,表示二進制轉文本
                }
            }
        }

        Button {
            id:tipBtn
            height: 32
            width: parent.width - 20
            text:qsTr("說明")
            anchors.top: convertBtn.bottom
            anchors.margins: 5
            anchors.horizontalCenter: parent.horizontalCenter

            onClicked: {
                msgDialog.open(); //彈出消息對話框
            }
        }

        MessageDialog {
            id:msgDialog
            width: 520
            height: 180
            //buttons: MessageDialog.Ok
            text: "文本二進制互轉工具使用說明"
            informativeText: "\n二進制轉文本,會在每個字節前面加\"0x\"頭部,並使用空格分隔;\n文本轉二進制,自動過濾\"0x\"、空格、換行符;"
        }

        FileDialog {
            id:fds
            title: "選擇文件"
            folder: shortcuts.desktop
            selectExisting: true
            selectFolder: false
            selectMultiple: false
            nameFilters: ["txt文件 (*.txt)","bin文件 (*.bin)"]
            onAccepted: {
                labels.text = fds.fileUrl;                
                FILECONVERT.fileName = fds.fileUrl
                tipLabel.text = ""
                //根據文件名後綴,自動選擇轉換類型
                var suffix = FILECONVERT.fileName.substring(FILECONVERT.fileName.length - 4);
                if(suffix == ".txt")
                    isTxt2Bin = true;
                else
                    isTxt2Bin = false;
            }

            onRejected: {
                //if (labels.text == "")
                    //tipLabel.text = "未選中文件"
            }
        }

        //下面是轉換類型,由兩個勾選框實現
        //isTxt2Bin記錄轉換類型,CheckBox的操作會修改isTxt2Bin,觸發IsTxt2BinChanged信號
        //從而onIsTxt2BinChanged槽函數被執行,文本轉二進制/二進制轉文本爲非此即彼的關係
        Column {
            anchors.top: tipBtn.bottom
            anchors.topMargin: 2
            anchors.left: parent.left
            anchors.leftMargin: 10

            CheckBox {
                id: txt2binCB
                text: qsTr("文本轉二進制")
                checked: true

                onClicked: {
                    isTxt2Bin = !isTxt2Bin
                }
            }
            CheckBox {
                id: bin2txtCB
                text: qsTr("二進制轉文本")
                checked: false

                onClicked: {
                    isTxt2Bin = !isTxt2Bin
                }
            }
        }
    }

    onIsTxt2BinChanged: {
        txt2binCB.checked = isTxt2Bin
        bin2txtCB.checked = !isTxt2Bin
    }

    //底部的顯示欄,用於顯示執行狀態信息
    footer: Item {
        height: 20
        width: parent.width

        Rectangle {
            anchors.fill: parent
            anchors.topMargin: 2
            color: "#EEEEEE"
            Label {
                id: tipLabel
                objectName: "tipLabelObj"
                anchors.left: parent.left
                anchors.leftMargin: 5
                font.family: "宋體"
                font.pixelSize: 14
                //anchors.horizontalCenter: parent.horizontalCenter
            }
        }
    }
}

上面qml調用了C++對象FileConvert的fileName屬性和doConvert方法,FileConvert對象定義如下:

#ifndef FILE_CONVERT_H
#define FILE_CONVERT_H

#include <QObject>

class FileConvert : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString fileName READ getFileName WRITE setFileName NOTIFY fileNameChanged)
    Q_PROPERTY(int process READ getProcess WRITE setProcess NOTIFY processChanged)
public:
    explicit FileConvert(QObject *parent = nullptr);

    QString getFileName() const{return fileName;}
    void setFileName(QString s){fileName = s; emit fileNameChanged();}

    int getProcess() const{return process;}
    void setProcess(int v){process = v; emit processChanged();}

signals:
    void fileNameChanged();
    void processChanged();

public slots:
public:
    Q_INVOKABLE void doConvert(int type);
private:
    QString fileName;
    int process;
    int txt2bin(FILE* fpin,FILE* fpout, long size);
    int bin2txt(FILE* fpin,FILE* fpout, long size);
};

#endif // FILE_CONVERT_H

上面包含了qml調用C++需要的定義,可參考qml與C++交互的相關內容,下面看下doConvert的實現(qml調用C++的方法,定義時必須加上Q_INVOKABLE關鍵字)

void FileConvert::doConvert(int type)
{
    char input[4096];
    char output[4096];
    char tmp[4096];
    std::string str;
    FILE* fp;
    FILE* outfp;
    //struct stat statbuf;
    long size;
    int ret;

    memset(input, 0, sizeof(input));
    memset(output, 0, sizeof(output));
    memset(tmp, 0, sizeof(tmp));

    str = fileName.toStdString();
    strcpy(tmp, str.c_str());
    if(strlen(tmp) == 0) {
        qDebug()<<"fileName is Empty";
        return;
    }
    //使用fopen打開文件,需要去掉"file:///"前綴
    memmove(input, tmp + strlen("file:///"), strlen(tmp) - strlen("file:///"));
    qDebug()<<"fileName:"<<fileName<<", input:"<<input;

    //以讀、二進制方式打開文件
    fp = fopen(input,"rb+");
    if(fp == NULL)
    {
        qDebug()<<"open failed "<<input;
        return;
    }

    //stat(input, &statbuf);
    //size = statbuf.st_size;
    //讀取文件大小
    fseek(fp,0L,SEEK_END);
    size=ftell(fp);
    fseek(fp,0L,SEEK_SET);

    qDebug()<<"file size "<<size;

    //根據轉換類型,增加目標文件的後綴
    sprintf(output, "%s%s", input, (type == CONVERT_TXT2BIN) ? ".bin" : ".txt");
    outfp = fopen(output,"wb+");
    if(outfp == NULL)
    {
        qDebug()<<"open failed "<<output;
        fclose(fp);
        return;
    }

    //表示轉換進度
    process = 0;

    //根據轉換類型,調用不同的方法進行轉換
    if(type == CONVERT_TXT2BIN) {
        ret = txt2bin(fp, outfp, size);
    }
    else {//if(type == CONVERT_BIN2TXT) {
        ret = bin2txt(fp, outfp, size);
    }

    //根據執行轉換函數的返回值,設置qml底部顯示欄顯示(c++調用qml成員)
    if(ret == -FILE_FD_ERR) {
        QVariant msg = "文件讀寫失敗";
        showMessage(msg);
    }
    else if(ret == -FILE_FMT_ERR) {
        QVariant msg = "文件格式錯誤";
        showMessage(msg);
    }
    else {
        QVariant msg = "完成";
        showMessage(msg);
    }

    fclose(fp);
    fclose(outfp);
    return;
}
  • 工程源碼

項目代碼已上傳github託管,下載https://github.com/baiyou123/TxtBinConverter

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章