基於android獲得SIM卡三種格式的UCS2編碼

來源:互聯網
上載者:User

之前的工作涉及到SIM卡的UCS2編碼,需要將字元用81格式編碼,在網上找了許多資料,結合自己的研究,現和大家一起分享。

本文主要介紹如何獲得字元的80,81,82格式編碼,代碼在andoid平台上測試,成功儲存連絡人資訊並成功解碼。由於有些東西是自己研究所得,難免會有錯誤,如有不實的地方,歡迎批評指正。

解碼檔案及方法: frameworks/base/telephony/java/com/android/internal/telephony/uicc/IccUtil.java的adnStringFieldToString()方法。

什麼是UCS2編碼?

UCS2(Unicode Character Set)是一種字元編碼方式,2代表一個字元編碼後為2個位元組。

我們在SIM卡上儲存連絡人時就是使用UCS2編碼。

 

SIM卡上的UCS2編碼主要有三種格式:80,81,82

 

下面說明每種格式的編碼方式:

‘80’格式:

1.第一個位元組為0x80

2.之後的位元組為UCS字元,每個字元佔用2個位元組。(在android平台上用UTF-16BE編碼)。

例:

編碼後的字元為:4e1c 65b9 4e0d 8d25

用80格式表示是:80 4e1c 65b9 4e0d 8d25

‘81’格式:

1. 第一個位元組為0x81

2.第二個位元組為字串長度

3.第三個位元組為基址,為一個UCS碼的第15位到第8位(0xxx xxxx x000 000)

4.第四個位元組以後為81格式的UCS碼

例:

編碼後的字元為:0035 0416 0438 043a

用81格式表示是:81 04 08 35 96 b8 ba

下面我們以這個例子來看一下基址以及字元編碼的獲得:

取得第一個位元組不是’00’的字元編碼:

0416 = 0001 0110

0438 = 0011 1000

043a = 0011 1010

所以基址為0000 1000,也就是08

然後用基址算出這4個字元的81編碼:

0035 = 0000 0000 0011 0101,第8位為0,所以它的81編碼為0011 0101,也就是53

0416 = 0000 0100 0001 0110,基址左移7位為0000 0100 0011 1010 = 0400,減去基址以後為16,也就是0001 0110,然後最高位補1,為1001 0110,即96

後面的以此類推,為b8,ba

從這裡可以看出,81格式只能在第15位到第8位相同的情況下才能進行。也就是說編碼的範圍只由後7位決定,而且是連續的,也就是2的7次方,即128個字元。所以中文並不適合用81格式來編碼,因為兩個漢字之間的UCS編碼很可能大於128。

‘82’格式:

1.第一個位元組為0x82

2.第二個位元組為字串長度

3.第三和第四個位元組為基址,基址可以為UCS碼中第一個位元組不為0的最小值。

4.第四個位元組以後為82格式的UCS碼

例:

編碼後的字元為:0061 4e0d 4e4e 4e86

用82格式表示是:82 04 4e0d 61 80 c1 f9

下面我們以這個例子來看一下基址以及字元編碼的獲得:

選取UCS碼第一個位元組不為0的最小值,此處的四個字元第一個位元組都不為0,所以選擇這四個字元的最小值作為基址,也就是4e0d

然後用基址算出這4個字元的82編碼:

0061 = 0000 0000 0110 0001,第8位為0,所以它的82編碼為61

4e0d = 0100 1110 0000 1101,減去基址4e0d等於0,最高位補1為1000 0000,即80

4e4e = 0100 1110 0100 1110,減去基址等於41,最高位補1為1100 0001,即c1

剩下的4e86以此類推。

82格式和81有同樣的限制,同樣也只能表示128個字元,而且也要求連續。

那我們在什麼情況下選擇80,81還是82格式呢?

1.如果可能的話,盡量選擇81格式,因為同樣大小的位元組用81格式可以表示最多的字元。如果有14個位元組可以儲存,那麼使用81格式可以儲存11個字元(3+N)。但是81格式最多隻能表示128個字元。

2.選擇82格式,14個位元組可以儲存10個字元(4+N),同樣最多隻能表示連續的128個字元。

3.選擇80格式,14個位元組可以儲存6個字元(1+2N),但是80格式可以表示的範圍廣,可以從0000到FFFF。所以在大多數情況下漢字只能用80格式。

 

下面是一個用java寫的例子以及測試程式:

[] ucs2ToAlphaField([] src, srcOff, destOff, min = 0x7FFF max = 0 (srcLen > 2 (i = 0; i < srcLen; i += 2 (src[srcOff + i] != 0 temp = () (((src[srcOff + i] << 8) & 0xFF00) | + i + 1] & 0xFF (temp < 0 max = min + 130 (min > min = (max < max = ((max - min) < 129 (() (min & 0x80) == () (max & 0x80 dest = [srcLen / 2 + 3 dest[destOff + 1] = () (srcLen / 2 dest[destOff] = () 0x81 min = () (min & 0x7F80 dest[destOff + 2] = () ((min >> 7) & 0xFF outOff = destOff + 3 dest = [srcLen / 2 + 4 dest[destOff + 1] = () (srcLen / 2 dest[destOff] = () 0x82 dest[destOff + 2] = () ((min >> 8) & 0xFF dest[destOff + 3] = () (min & 0xFF outOff = destOff + 4 (i = 0; i < srcLen; i += 2 (src[srcOff + i] == 0 dest[outOff] = () (src[srcOff + i + 1] & 0x7F temp = () ((((src[srcOff + i] << 8) & 0xFF00) | + i + 1] & 0xFF)) - dest[outOff] = () (temp | 0x80 outOff++ dest = [srcLen + 1 dest[destOff] = () 0x80 System.arraycopy(src, 0, dest, 1 }View Code String src = "5Жик" [] dest = [] srcByte = src.getBytes("UTF-16BE" dest = ucs2ToAlphaField(srcByte, 0, srcByte.length, 0 ( i = 0; i < srcByte.length; i++ System.out.print(Integer.toHexString(srcByte[i] & 0xFF) + " " ( i = 0; i < dest.length; i++ System.out.print(Integer.toHexString(dest[i] & 0xFF) + " " } }View Code

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.