Qt中的字符編碼轉換:UTF8、Unicode、GBK、ASCII、16進制字符、16進制數值

前言

字符編碼方式多種多樣,往往不同的應用、不同的設備、不同的系統上使用的字符編碼不同,因此想要設計魯棒性強的軟件,就必須掌握對字符編碼的轉化機制和具體實現,特別是在Qt這樣的跨平臺框架上。特別地,本文就Qt串口通信助手中需要的字符編碼轉換進行探討。

簡述

ASCII

ASCII ((American Standard Code for Information Interchange): 美國信息交換標準代碼)是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其他西歐語言。它是最通用的信息交換標準,並等同於國際標準ISO/IEC 646。ASCII第一次以規範標準的類型發表是在1967年,最後一次更新則是在1986年,到目前爲止共定義了128個字符。

GBK

GBK全稱《漢字內碼擴展規範》(GBK即“國標”、“擴展”漢語拼音的第一個字母,英文名稱:Chinese Internal Code Specification) ,中華人民共和國全國信息技術標準化技術委員會1995年12月1日製訂,國家技術監督局標準化司、電子工業部科技與質量監督司1995年12月15日聯合以技監標函1995 229號文件的形式,將它確定爲技術規範指導性文件。這一版的GBK規範爲1.0版。

Unicode

Unicode(統一碼、萬國碼、單一碼)是計算機科學領域裏的一項業界標準,包括字符集、編碼方案等。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。

UTF-8

UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是針對Unicode的一種可變長度字符編碼。它可以用來表示Unicode標準中的任何字符,而且其編碼中的第一個字節仍與ASCII相容,使得原來處理ASCII字符的軟件無須或只進行少部份修改後,便可繼續使用。因此,它逐漸成爲電子郵件、網頁及其他存儲或傳送文字的應用中,優先採用的編碼。

應用場景

  • ASCII編碼只使用一個字節表示字符,佔用空間小,因此在嵌入式領域非常常見,常用於數據傳輸。
  • GBK編碼常見於Window平臺,使用雙字節編碼,由於是國家標準,主要用於中文編碼,因此通用性有一定侷限性,
  • Unicode是計算機科學領域裏的一項業界標準,通用性較強,但是需要的存儲空間更多。
  • UTF-8是針對Unicode編碼過大的一種優化,採用變長度字節(1-6個直接)存儲,且兼容ASCII,逐漸變得流行。
  • Unicode與UTF-8的區別在於,Unicode是字符集,而UTF-8是Unicode的編碼方式。
  • 需要通用性採用UTF-8,需要更多存儲空間採用GBK。

開發環境

  • Qt Creator 4.10.1
  • Qt 5.13.2(默認爲Unicode編碼)
  • MinGw 32-bit編譯器
  • Win10系統(默認爲GBK編碼)

編碼轉換

16進制數值轉換爲16進制字符

  • 轉換機制:將串口接受到的數據按比特進行字符化
QString CharEncodingTrans::QByteArray_to_HexQString(const QByteArray &data)
{
    char tmp_byte;
    QString tmp_qstr;
    foreach(char byte, data)
    {
        // 高字節
        tmp_byte = (byte & 0xF0)>>4;
        tmp_qstr += (tmp_byte < 10) ? tmp_byte+'0' : tmp_byte+'A'-10;

        // 低字節
        tmp_byte = byte&0x0F;
        tmp_qstr += (tmp_byte < 10) ? tmp_byte+'0' : tmp_byte+'A'-10;
        tmp_qstr += ' ';
    }
    return tmp_qstr;
}

16進制數值轉化爲字符串

  • 筆者的開發環境爲win10,所以QTextCodec::codecForName("System")採用的編碼爲GBK編碼,因此tc->toUnicode()在這裏的意義是從GBK編碼轉換爲Unicode,進而在Qt的textEdit上顯示。
QTextCodec* tc = QTextCodec::codecForName("System");
tmp_qstr = tc->toUnicode(data)

16進制字符串轉換爲Unicode字符串

  • 轉換機制:僅16進制字符串先轉換爲16進制數值,再通過16進制數值轉換爲字符串。
  • 使用Qt中QByteArray的append函數,ascii_data.append(str);將16進制字符串儲存在QByteArray中,再通過QByteArray::fromHex()靜態函數將QByteArray的16進制字符串轉換成對應的ascii碼字符串。
  • 最後通過QTextCodec將字符串編碼轉化爲Qt默認的Unicode編碼
QString HexQString_to_QString(const QString &text)
{
    QTextCodec *tc = QTextCodec::codecForName("System");
    // 將Hex字符串轉換爲Ascii字符串
    QString temp;
    QByteArray ascii_data;
    QStringList temp_list = text.split(' ', QString::SkipEmptyParts);
    foreach(QString str, temp_list)
    {
        ascii_data.append(str);
    }
    // 將ascii_data中的16進制數據轉化爲對應的字符串,比如\x31轉換爲"1"
    temp = tc->toUnicode(QByteArray::fromHex(ascii_data));
    return temp;
}

Unicode字符串轉化爲16進制字符串

  • 轉換機制:將16進制字符串先轉換爲16進制數值,這裏通過使用QByteArray的append函數。但是這裏需要注意的是,由於是開發在windows上的程序,所以編碼採用GBK編碼,所以要講中文對應的16進制編碼換成GBK編碼,然後再轉化爲字符串。
  • 同時由於QByteArray中存儲的16進制數,並不是以數值存在的,而是以字符串形式存在的,所以要使用toHex()函數,將“\x31”轉換0x31。
QString CharEncodingTrans::QString_to_HexQString(const QString &text)
{
	QTextCodec *gbk = QTextCodec::codecForName("System");
    QString temp;
    QByteArray hex_data;
    foreach(QChar byte, text)
    {
        hex_data.append(gbk->fromUnicode(byte));
    }
    // 將hex_data中的16進制轉化爲
    temp = gbk->toUnicode(hex_data.toHex()).toUpper();
    // 在字符串中每兩個字符添加一個空格,爲了防止疊加效應,選擇從後面開始添加
    for(int i = temp.length(); i > 0; i -=2)
        temp.insert(i, ' ');
    return temp;
}

總結

  1. Qt中的QTextCodec提供強大的字符集轉換功能
  2. QByteArray功能強大,可以作爲很多字符轉換操作的載體
    • QByteArray::fromHex將存儲在QByteArray中的16進制字符串轉換爲對應的ascii字符
    • QByteArray::toHex將16進制字符串轉化爲對應的數值
  3. Qt默認使用Unicode作爲字符編碼,window默認使用GBK作爲字符編碼

參考資料

  1. https://baike.baidu.com/item/ASCII/309296?fr=aladdin
  2. https://baike.baidu.com/item/GBK%E5%AD%97%E5%BA%93/3910360?fromtitle=GBK&fromid=481954&fr=aladdin
  3. https://baike.baidu.com/item/Unicode/750500?fr=aladdin
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章