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

最近有个项目,涉及到通过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;
	}
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Base64 编码是一种将二进制数据编码成字符串的方法,常用于在网络上传输或存储数据。它使用64种字符来表示二进制数据,这些字符包括大写字母、小写字母、数字以及一些特殊字符。 与十六进制编码相比,Base64 编码的优势在于它可以表示任意二进制数据,而十六进制编码只能表示整数。此外,Base64 编码后的字符串也更短,因为它使用了更少的字符来表示二进制数据。 对于文本数据Base64 编码后的字符串中只包含可打印字符,因此更容易阅读和处理。 另外,在不同的应用中,Base64 编码也有不同的用途。例如,在电子邮件中,它可用于在邮件正文和附件中传输二进制数据;在 HTTP 协议中,它可用于在请求和响应头中传输二进制数据。 ### 回答2: 十六进制字符串和Base64编码都是常用的数据表示方式,但它们有不同的应用场景和特点。 首先,十六进制字符串是一种用16个字符(0-9,A-F)表示二进制数据的表示方法。它简单直观,便于人类阅读和理解,适用于某些特定的应用场景,比如显示内存地址、计算机中的数据传输和调试等。然而,十六进制字符串的表示方式需要更多的字符来表达相同的二进制数据,使其相对于二进制数据来说冗余度较高。 相比之下,Base64编码则是一种将二进制数据转换成ASCII字符的编码方式。它使用64个字符(包括大小写字母、数字和一些特殊字符)来表示二进制数据,不仅可以节省存储空间,而且还可以在文本协议中传输二进制数据Base64编码常见于电子邮件传输、URL参数传递、图片传输等场景。它可以解决文本和二进制之间的转换问题,提高数据在不同系统和环境中的兼容性与可传输性。 因此,虽然十六进制字符串和Base64编码都是表示二进制数据的方法,但它们有不同的应用场景和特点,具体选择哪种编码方式需要根据具体的需求和使用环境来确定。 ### 回答3: 十六进制字符串和Base64编码是两种不同的编码方式,分别用于不同的场景。 首先,十六进制是一种用16个不同的字符来表示数字的方法,它包含了数字0-9和字母A-F,共16个字符。十六进制字符串主要应用于计算机领域,用于表示二进制数据,如内存地址、文件指纹等。由于它的表示方式较为简单直观,方便机器进行处理和计算,因此在计算机领域广泛使用。 而Base64编码是一种将二进制数据转换为可打印字符的编码方式。它使用64个字符(包括大小写字母、数字和两个特殊字符)来表示二进制数据,通过将每个6个比特位的二进制数据转换成相应的可打印字符来实现编码Base64编码主要用于数据传输、存储和表示,它可以将二进制数据转换成纯文本形式,以便在不支持二进制的系统中传输或保存数据。 为什么在某些情况下要将十六进制字符串转换为Base64编码呢?一方面,Base64编码后的数据长度相对较短,可以节省存储空间和传输带宽;另一方面,Base64编码后的数据只包含可打印字符,更适合在文本环境中使用,例如作为URL参数传递、存储在文本文件中等。因此,在需要将二进制数据以纯文本形式表示或传输时,可以选择使用Base64编码。 总而言之,十六进制字符串和Base64编码是两种编码方式,各有其适用的场景。根据实际需求选择合适的编码方式可以更好地满足数据处理和传输的要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值