在Windows的控制台介面下輸出BMPString的內容

來源:互聯網
上載者:User

標籤:c語言   unicode   

        在解析X.509格式的數位憑證時,有時候從認證中提取出的 commonName、countryName 等項的值類型是 BMPString,特別當這些值是中文的時候。此時如果在 Windows 的控制台下使用使用 wprintf() 輸出這些值,顯示的結果是亂碼。

        為了搞清楚產生亂碼的原因,找到一張認證,查看其中的 countryName,對應的 ASN.1 編碼類別型是BMPString,編碼是:0x1E, 0x4, 0x4E, 0x2D, 0x56, 0xFD,對應值為“中國”。在網上查詢了”中國“對應的 Unicode 編碼是 {0x4E, 0x2D, 0x56, 0xFD},0x4E, 0x2D 對應字元“中”,0x56, 0xFD 對應字元“國” 。將字元 0x4E, 0x2D, 0x56, 0xFD 順序放入一個字元數組,依次調用 setlocale() 、wprintf() 函數,輸出為亂碼。

        在網上查了一下,對於BMPString 的 ASN.1 編碼,其負載部分採用 Unicode 編碼中的 UTF-16 編碼方式,一個字元的編碼佔兩個位元組。但是這兩個位元組中哪一個用來存放編碼的高 8 位、哪一個用來存放編碼的低 8 位,在不同的地方有不同處理方式。在 ASN.1 編碼中,一般對於負載部分的編碼都採用 big-endian 順序,所以從數位憑證中提取出來的“中國”對應的編碼為 {0x4E, 0x2D, 0x56, 0xFD},其順序是 Big-endian 順序。在 Intel 的 CPU 上通常使用 little-endian 位元組順序,Windows 中處理資料也採用 little-endian 順序,所以在 Windows 中試圖輸出Big-endian 順序編碼的字元,當然會產生亂碼。(順便說一句,對於 UniversalString 的ASN.1 編碼,其負載部分採用Unicode 編碼中的 UTF-32 編碼方式,一個字元的編碼佔四個位元組。)

       要解決輸出亂碼的問題,方法是在輸出前,先將 Big-endian 順序編碼的字元轉換為 little-endian 順序編碼的字元,然後再輸出,就不會產生亂碼了。下面給出一個樣本程式:

/************************************************** * Author: HAN Wei * Author's blog: http://blog.csdn.net/henter/ * Date: Oct 30th, 2014 * Description: demonstrate how to print BMPString  on Windows console**************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <locale.h>/***************************************************函數名稱:InterchangeEndianOrder*功能: 顛倒 BMPString 編碼中每一個 UTF-16字元 的 endian 順序*參數:     BMPString     [in]           BMPString_len [in]   BMPString 的長度,以位元組為單位*傳回值:    0   成功-1  失敗*備忘:  BMPString 通常由 UTF-16 字元組成,UTF-16 字元有時採用 big-endian 順序,  有時採用 little-endian 順序,本函數的功能是顛倒 endian 順序**************************************************/int InterchangeEndianOrder(unsigned char *BMPString, unsigned int BMPString_len){  int i;  unsigned char *p, temp;  if ( (BMPString_len % 2) != 0 )  {#ifdef _DEBUGprintf("Invalid BMPString byte length: %d.\n", BMPString_len);printf("BMPString byte length must be multiple of 2!\n");#endifreturn (-1);  }    p = BMPString;  for (i=0; i < (int)( BMPString_len/2); i++)  {temp=*p;*p=*(p+1);*(p+1)=temp;p+=2;  }  return 0;}/***************************************************函數名稱:PrintBMPString*功能: 在 Windows 控制台介面下輸出 BMPString*參數:     BMPString     [in]           BMPString_len [in]   BMPString 的長度,以位元組為單位*傳回值:    0   成功-1  失敗**************************************************/int PrintBMPString(unsigned char *BMPString, unsigned int BMPString_len){  unsigned char *buffer;  unsigned int buffer_len;  buffer_len = BMPString_len +2; /* 緩衝區大小比 BMPString 的位元組長度多出兩個位元組,                                    這兩個位元組用來存放 UTF-16 編碼的字串結束符 \0,                                    其對應編碼是 0x0, 0x0 */  if ( !(buffer=(unsigned char *)malloc(buffer_len)) )  {#ifdef _DEBUGprintf("malloc() function failed!\n");#endifreturn (-1);  }  memset(buffer, 0, buffer_len);  memcpy(buffer, BMPString, BMPString_len);  setlocale(LC_ALL, "chs");  InterchangeEndianOrder(buffer, BMPString_len);  wprintf(L"BMPString: %ls\n", (wchar_t *)buffer);  free(buffer);  return 0;}int main(void){  int error_code;  unsigned char BMPString_data1[]={0x4e, 0x2d, 0x56, 0xfd};  /* 中文字串"中國"對應的 Unicode 編碼 */  unsigned char BMPString_data2[]={0x0, 0x55, 0x0, 0x73, 0x0, 0x65, 0x0, 0x72};  /* 英文字串"User"對應的 Unicode 編碼 */  wchar_t str[]=L"中國";  unsigned char *p;  int i;  if ( error_code = PrintBMPString(BMPString_data1, sizeof(BMPString_data1)) )  {printf("Print BMPstring on Windows console failed!\n");return (-1);  }  if ( error_code = PrintBMPString(BMPString_data2, sizeof(BMPString_data2)) )  {printf("Print BMPstring on Windows console failed!\n");return (-1);  }/* 下面給出了說明 unicode 編碼的字元在 Windows 中是如何存放的一個例子,   從顯示結果可以看出每一個 UTF-16 字元都是以 little-endian 順序存放 */  printf("\n");  setlocale(LC_ALL, "chs");  wprintf(L"%ls\n", (wchar_t *)str);  p=(unsigned char *)str;  printf("Wide character length is: %d\n", wcslen(str));  printf("Unicode encode on Windows platform: ");  for (i=0; i < (int)(wcslen(str)*2); i++)  {printf("0x%x  ", *p);p++;  }  printf("\n");  system("pause");  return 0;}

輸出結果如:

在Windows的控制台介面下輸出BMPString的內容

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.