基于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()方法。
我们在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个字符,而且也要求连续。
2.选择82格式,14个字节可以存储10个字符(4+N),同样最多只能表示连续的128个字符。
3.选择80格式,14个字节可以存储6个字符(1+2N),但是80格式可以表示的范围广,可以从0000到FFFF。所以在大多数情况下汉字只能用80格式。
下面是一个用java写的例子以及测试程序:
View Code
本文主要介绍如何获得字符的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
相关文章推荐
- 基于android获得SIM卡三种格式的UCS2编码
- Android中自定义View的研究(三) -- 获得Bitmap的三种方法
- SIM卡中UCS2编码的三种格式(80,81,82)分析
- Android中获得Message对象三种方式的去呗
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计
- android解析XML总结(SAX、Pull、Dom三种体式格式)
- 基于android源码基础的API文档制作,CHM格式制作
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计
- android获得图片资源的三种方式
- Android数据传输格式(基于JSON格式)
- 关于android下获得的date转化为特定显示格式
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计 推荐
- Android HAL实现的三种方式(2) - 基于Service的HAL设计
- Android HAL实现的三种方式(2) - 基于Service的HAL设计
- android获得Bitmap的三种方法
- SIM卡中UCS2编码的三种格式(80,81,82)分析
- Android HAL实现的三种方式(3) - 基于Manager的HAL设计
- SIM卡中UCS2编码的三种格式(80,81…
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计