Base8编码:通过数字传输二进制数据

来源:互联网 发布:linux 登录日志查询 编辑:程序博客网 时间:2024/05/18 02:05

最近有个项目,涉及到通过SS或者USSD信道完成数据的交互。以下是SS和USSD的说明:

SS

Supplementary Service,补充服务,比如控制号码显示,呼叫转移等服务的号码串。这些号码串是每部GSM/UMTS/LTE手机中的固定服务号码,运营商是不能对它进行修改的。当手机系统接受到这些服务号码后,先在手机内部进行处理后,再传给网络。比如你随便拿个手机,在拨号盘输入*21*123456789#然后点击发送,这个时候你所有的来电都会直接转移到123456789。

USSD

与SS相对应的是Unstructured Supplementary Service Data。从字面上看,是非结构化的补充字符,曾经我以为字符串格式上的不同是SS和USSD间最大的区别,后来发现自己大错特错了:单从字符串格式上是没法区分的。那他俩到底有啥区别?一,USSD基本都是运营商根据自己的服务自己定制的,而SS就像上面说的是每个手机固有的;二,SS在发送给网络前,手机首先会自己处理一下,而USSD是完全透明的传送给网络。

SS和USSD都必须点击发送后才能生效,而Manufacturer defined MMI codes和SIM control codes都不需要点击,输入后直接生效。

基于定义,USSD基本上是通过手机拨号键盘发送的,所以只支持0-9以及*,#这12个字符。怎么把Hex编码转化为USSD字符承载呢?我想到了Base64编码的原理,无非就是通过bit切割将数据值域切为有效字符的个数范围内,并通过查表映射为有效字符。代码如下,有类似需求的朋友说不定可以复用一下:

package com.broadthinking.alg;/** * 将编码字节以3个8位字节一组,转化为8个3位的字节,并查表得到8个字符('0'-'7')。 * 如果编码字节不足3个字节,则用0填充。并在输出字符末尾填充'8'来指示有几个填充字节。 * ------------------------------- * 数值字符 * ------------------------------- * 0'0' * 1'1' * 2'2' * 3'3' * 4'4' * 5'5' * 6'6' * 7'7' * ------------------------------- * @author caesarzou * */public class Base8 {public static void main(String [] args) throws Exception {byte [][] test = {{(byte)0x1F},{(byte)0xFE,(byte)0xDE},{(byte)0xFE,(byte)0x10,(byte)0xDE},{(byte)0xFF,(byte)0x10,(byte)0x00,(byte)0x11,(byte)0x22,(byte)0x33,(byte)0xFF}};for(int i=0;i<test.length;i++) {byte [] resb = test[i];for(int j=0;j<resb.length;j++) {System.out.print(Integer.toHexString(resb[j]&0x00FF));}System.out.println();char [] res = Base8.encode(resb, 0, resb.length);System.out.println(String.valueOf(res));resb = Base8.decode(res);for(int j=0;j<resb.length;j++) {System.out.print(Integer.toHexString(resb[j]&0x00FF));}System.out.println();System.out.println();}}public static char [] encode(byte [] data, int offset, int length) {int pad = (3-length%3);if(pad == 3) {pad = 0;}int oplength = length+pad;int opblock  = oplength/3;byte [] opdata = new byte[oplength];char [] rsdata = new char[8*opblock];System.arraycopy(data, offset, opdata, 0, length);for(int i=0;i<opblock;i++) {int tmpdata = ((opdata[i*3]<<16) & 0x00FF0000) | ((opdata[i*3+1]<<8) & 0x0000FF00)| (opdata[i*3+2] & 0x000000FF);rsdata[i*8] = (char)(0x30 | ((tmpdata>>21) & 0x07));rsdata[i*8+1] = (char)(0x30 | ((tmpdata>>18) & 0x07));rsdata[i*8+2] = (char)(0x30 | ((tmpdata>>15) & 0x07));rsdata[i*8+3] = (char)(0x30 | ((tmpdata>>12) & 0x07));rsdata[i*8+4] = (char)(0x30 | ((tmpdata>>9) & 0x07));rsdata[i*8+5] = (char)(0x30 | ((tmpdata>>6) & 0x07));rsdata[i*8+6] = (char)(0x30 | ((tmpdata>>3) & 0x07));rsdata[i*8+7] = (char)(0x30 | (tmpdata & 0x07));}for(int i=0;i<pad;i++) {rsdata[rsdata.length-1-i] = (char)0x38;}return rsdata;}public static byte [] decode(char [] code) {int pad = 0;if(code[code.length-1] == (char)0x38) {if(code[code.length-2] == (char)0x38) {pad = 2;} else {pad = 1;}}int opblock = code.length/8;byte [] rsdata = new byte[opblock*3];for(int i=0;i<opblock;i++) {int tmpdata = 0;tmpdata |= (code[i*8]& 0x07)<<21;tmpdata |= (code[i*8+1] & 0x07)<<18;tmpdata |= (code[i*8+2] & 0x07)<<15;tmpdata |= (code[i*8+3] & 0x07)<<12;tmpdata |= (code[i*8+4] & 0x07)<<9;tmpdata |= (code[i*8+5] & 0x07)<<6;tmpdata |= (code[i*8+6] & 0x07)<<3;tmpdata |= (code[i*8+7] & 0x07);rsdata[i*3]   = (byte)(tmpdata>>16);rsdata[i*3+1] = (byte)(tmpdata>>8);rsdata[i*3+2] = (byte)(tmpdata);}byte [] crsdata = new byte[rsdata.length-pad];System.arraycopy(rsdata, 0, crsdata, 0, crsdata.length);return crsdata;}}


2 0
原创粉丝点击