时间:2013-08-01 18:16:47

UUencode 编码,UU编码介绍、UUencode编码转换原理、算法

分享到:

 

UUencode编码起先用在unix网络中,先是Unix系统下将二进制的资料借由uucp邮件系统传输的一个编码程式,也是一种二进制到文字的编码。不属于MIME编码中一员。它也是定义了用可打印字符表示二进制文字一种方法,并不是一种新的编码集合。主要解决,二进制字符在传输、存储中问题。它早期在电子邮件中使用较多,最近这些年来基本上被MIME 中Base64所取代了。E-mail中一般采用UU、MIME、BINHEX三种编码标准! 我想,了解下这种编码将二进制字符转换为可打印字符实现思路!对我们以后做类似处理工作,应该会有很多的启示。

UUencode编码过程

Uuencode将输入资料以每三个字节为单位进行编码,如此重复进行。如果最后剩下的资料少于三个字节,不够的部份用零补齐。这三个字节共有24个Bit,以6-bit为单位分为4个群组,每个群组以十进制来表示所出现的数值只会落在0到63之间。将每个数加上32,所产生的结果刚好落在ASCII字符集中可打印字符(32-空白…95-底线)的范围之中。每60个编码输出(相当于45个输入字节)将输出为独立的一行,每行的开头会加上长度字符,除了最后一行之外,长度字符都应该是’M'这个ASCII字符(77=32+45),最后一行的长度字符为32+剩下的字节数目这个ASCII字符。如果是一个 0字节那它应该被转换为0×60而不是0×20,因为(前引用’`')优于 0×20(空格’ ‘)。

特点一:看到特点了吧,也是64字符,也是一组6位。怎么,怎么,跟我们的base64这么相似呢?是的,从这个定义中,我们确实发现它跟base64比起来很相似了。

特点二:它定义64字符,不用写映射表,是通过加32转换到可打印字符范围中。比起base64,更为简单!

思考问题:它的字符范围都是可打印字符,我们会发现64字符集合中,有很多是特殊字符:”!”#¥%&‘()*+=’” 等等。这些字符在不同应用中,可能都有些特殊用途。因此,在使用该编码时候,或许会出现一些问题。我想这也许是UUencode编码方法,逐渐被Base64所取代的原因吧。

UUencode 64字符集
可打印字符十进制ASCII值uuencode
二进制表示
uuencode
十进制表示
 可打印字符十进制ASCII值uuencode
二进制表示
uuencode
十进制表示
(space)32000 0000 @64100 00032
!33000 0011 A65100 00133
"34000 0102 B66100 01034
#35000 0113 C67100 01135
$36000 1004 D68100 10036
%37000 1015 E69100 10137
&38000 1106 F70100 11038
'39000 1117 G71100 11139
(40001 0008 H72101 00040
)41001 0019 I73101 00141
*42001 01010 J74101 01042
+43001 01111 K75101 01143
,44001 10012 L76101 10044
-45001 10113 M77101 10145
.46001 11014 N78101 11046
/47001 11115 O79101 11147
048010 00016 P80110 00048
149010 00117 Q81110 00149
250010 01018 R82110 01050
351010 01119 S83110 01151
452010 10020 T84110 10052
553010 10121 U85110 10153
654010 11022 V86110 11054
755010 11123 W87110 11155
856011 00024 X88111 00056
957011 00125 Y89111 00157
:58011 01026 Z90111 01058
;59011 01127 [91111 01159
<60011 10028 \92111 10060
=61011 10129 ]93111 10161
>62011 11030 ^94111 11062
?63011 11131 _95111 11163
     `96(1) 000 00064

UUencode编码转换过程

原始字符Cat
原始ASCII码(十进制)6797116
ASCII码(二进制)010000110110000101110100
新的十进制数值1654552
+3248863784
编码后的Uuencode字符0V%T
字符串:'Cat‘ 编码后是:oV%T

UUencode PHP实现过程

编码转换过程,与Base64类似!下面代码是实现过程,我们可以看看转换方法!

/**
 *uuencode编码*
 *@author 程默
 *@copyright http://blog.chacuo.net/
 *@param string $src 待处理字符串
 *@return string encode编码完字符串
 */
function c_uu_encode($src)
{
	///每次读取3个字节
	$lbyte = 3;
	////将原始的3个字节转换为4个字节
	$slen=strlen($src);
	$smod = ($slen%$lbyte);
	$snum = floor($slen/$lbyte);


	$desc = array();
	
	//将剩下字节以0字节补齐
	$src = $smod===0?$src:$src.str_repeat("\0",$lbyte-$smod);
	$snum = $smod===0?$snum:$snum+1;

	for($i=0;$i<$snum;$i++)
	{
		////读取3个字节
		$_arr = array_map('ord',str_split(substr($src,$i*$lbyte,$lbyte)));

		///计算每一个6位值
		$_dec = array();
		$_dec[]=$_arr[0]>>2;
		$_dec[]=(($_arr[0]&3)<<4)|($_arr[1]>>4);
		$_dec[]=(($_arr[1]&0xF)<<2)|($_arr[2]>>6);
		$_dec[]=$_arr[2]&63;
		
		///对每个6位值加上32,读取ascii码 如果6位值是0,以字符"`"代替
		foreach ($_dec as &$v)
		{
			$v = $v===0?'`':chr($v+32);
		}
		$desc = array_merge($desc,$_dec);
	}
	//return implode('',$desc);
	
	///以上代码只是进行转换,没有进一步进行
	//每60个编码输出(相当于45个输入字节)将输出为独立的一行,每行的开头会加上长度字符,除了最后一行之外,长度字符都应该是'M'这个ASCII字符(77=32+45),最后一行的长度字符为32+剩下的字节数目这个ASCII字符。
	$abyte = 60;
	$crlf = "\r\n";
	$alen = count($desc);
	$anum = floor($alen/$abyte);
	$amod = ($alen%$abyte);
	
	$adesc = array();
	
	for ($i=0;$i<$anum;$i++)
	{
		$adesc[]='M'.implode('',array_slice($desc,$i*$abyte,$abyte)).$crlf;
	}
	
	///截取后面剩余数组长度
	if($amod!==0)
	{
		///以下计算不满45字节编码情况
		$adesc[]=chr($amod/4*3+32+($smod?$smod-$lbyte:$smod)).implode('',array_slice($desc,-$amod)).$crlf;
	}
	
	return implode('',$adesc);	
}

 

以上只是按照转换过程,通过PHP代码实现方法!目前PHP没有UUencode转换模块!

UUencode编码

UUencode编码

该代码转换结果,跟使用工具转换结果一致。我查看了线上一些转换方法,很多结果不一致!最好,大家使用在线工具转换前,做一下比较!没有做过验证的代码,可能会给你带来麻烦!欢迎分享你的方法!

作者:程默的博客  QQ:8292669
原文网址:http://blog.chacuo.net/753.html
订阅保持关注:http://blog.chacuo.net/feed
本文版权归作者所有,欢迎转载,请务必添加原文链接。


 

留下评论

要发表评论,您必须先登录