您的位置:首页 > 移动开发 > Android开发

基于android获得SIM卡三种格式的UCS2编码

2013-06-12 22:57 309 查看
之前的工作涉及到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码

如果第8位是0(xxxx xxxx 0xxx xxxx),则此字符的81格式编码就用第7到1位表示(0000 0000 0xxx xxxx),第8位补0;

如果第8位是1(xxxx xxxx 1xxx xxxx),则此字符的81格式编码为UCS编码减去基址左移7位,第8位补1。

例:5Жик

编码后的字符为:0035 0416 0438 043a

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

下面我们以这个例子来看一下基址以及字符编码的获得:

取得第一个字节不是’00’的字符编码:

0416 = 0000 0100 0001 0110

0438 = 0000 0100 0011 1000

043a = 0000 0100 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码

如果第8位是0(xxxx xxxx 0xxx xxxx),则此字符的82格式编码就用第7到1位表示(0000 0000 0xxx xxxx),第8位补0;

如果第8位是1(xxxx xxxx 1xxx xxxx),则此字符的82格式编码为UCS编码减去基址,第8位补1。

例:a不乎了

编码后的字符为: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写的例子以及测试程序:

public static void main(String args[]){
String src = "5Жик";
try {
byte[] dest = null;
byte[] srcByte = src.getBytes("UTF-16BE");
dest = ucs2ToAlphaField(srcByte, 0, srcByte.length, 0, dest);
for (int i = 0; i < srcByte.length; i++) {
System.out.print(Integer.toHexString(srcByte[i] & 0xFF) + " ");
}
System.out.println();
for (int i = 0; i < dest.length; i++) {
System.out.print(Integer.toHexString(dest[i] & 0xFF) + " ");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: