Base85 与 Base64 相似,为一种把2进制的数据转换为文字数据的编码方式。它将4个2进制字节转换为5个字符,数据的增加率为25%。(Base64为33%)
Base85是在RFC-1924里面定义的。详细请参照RFC-1924
编码方式:
开始
从输入流读4个字节,把值放入uint类型的变量a中。
把a转换为85进制(除以85,求余数)的字符串,并写入输出流。
当输入流的剩余少于4个字节时
从输入流读入剩余的字节,把值放入uint类型的变量a中。
go to 3 (为了效率,这一步应该分为3种情况来写。)
结束
源码:
Base85CharSet.as
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package advancedflex.io.format {
/**
* Base85的字符集(Character Set)
*
* @see http://rfc.net/rfc1924.html RFC-1924
* @see Base85Decoder
* @see Base85Encoder
*/
public final class Base85CharSet {
/**
* 在<strong>RFC-1924</strong>里定义的一般的字符集(根据编码算字符)
*/
//0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~
public static const RFC_1924:Array =
[
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
"y", "z", "!", "#", "$", "%", "&", "(", ")", "*",
"+", "-", ";", "<", "=", ">", "?", "@", "^", "_",
"`", "{", "|", "}", "~",
];
/**
* 在<strong>RFC-1924</strong>里定义的一般的逆字符集(根据字符算编码)
*/
public static const DECODE_RFC_1924:Object =
{
"0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9,
"A":10, "B":11, "C":12, "D":13, "E":14, "F":15, "G":16, "H":17, "I":18, "J":19,
"K":20, "L":21, "M":22, "N":23, "O":24, "P":25, "Q":26, "R":27, "S":28, "T":29,
"U":30, "V":31, "W":32, "X":33, "Y":34, "Z":35, "a":36, "b":37, "c":38, "d":39,
"e":40, "f":41, "g":42, "h":43, "i":44, "j":45, "k":46, "l":47, "m":48, "n":49,
"o":50, "p":51, "q":52, "r":53, "s":54, "t":55, "u":56, "v":57, "w":58, "x":59,
"y":60, "z":61, "!":62, "#":63, "$":64, "%":65, "&":66, "(":67, ")":68, "*":69,
"+":70, "-":71, ";":72, "<":73, "=":74, ">":75, "?":76, "@":77, "^":78, "_":79,
"`":80, "{":81, "|":82, "}":83, "~":84
};
/**
* 在<strong>ascii85</strong>里定义的一般的字符集(根据编码算字符)
*/
//!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
public static const ASCII85:Array =
[
"!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
"+", ",", "-", ".", "/", "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9", ":", ";", "<", "=", ">",
"?", "@", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "[", "]",
"^", "_", "`", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
"r", "s", "t", "u", "v",
];
/**
* 在<strong>ascii85</strong>里定义的一般的字符集(根据编码算字符)
*/
public static const DECODE_ASCII85:Object =
{
"!":0, "\"":1, "#":2, "$":3, "%":4, "&":5, "'":6, "(":7, ")":8, "*":9,
"+":10, ",":11, "-":12, ".":13, "/":14, "0":15, "1":16, "2":17, "3":18, "4":19,
"5":20, "6":21, "7":22, "8":23, "9":24, ":":25, ";":26, "<":27, "=":28, ">":29,
"?":30, "@":31, "A":32, "B":33, "C":34, "D":35, "E":36, "F":37, "G":38, "H":39,
"I":40, "J":41, "K":42, "L":43, "M":44, "N":45, "O":46, "P":47, "Q":48, "R":49,
"S":50, "T":51, "U":52, "V":53, "W":54, "X":55, "Y":56, "Z":57, "[":58, "]":59,
"^":60, "_":61, "`":62, "a":63, "b":64, "c":65, "d":66, "e":67, "f":68, "g":69,
"h":70, "i":71, "j":72, "k":73, "l":74, "m":75, "n":76, "o":77, "p":78, "q":79,
"r":80, "s":81, "t":82, "u":83, "v":84
}
}
}Base85Encoder.as
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package advancedflex.io.format {
import flash.utils.ByteArray;
import flash.utils.IDataInput;
/**
* Base85的编码器
* <p>他把4个字节的2进制数据转换为5个字节的文本数据。数据的增加度为25%。</p>
*
* @see Base85CharSet
* @see Base85Decoder
*/
public class Base85Encoder {
/**
* 用String来编码
*
* @param src 原文
* @param charSet Base85字符集,默认为 Base85CharSet.RFC_1924
* @return 密文(原文编码后的数据)
*
* @see Base85CharSet#RFC_1924
*/
public static function encode(src:String, charSet:Array = null):String {
// Convert string to ByteArray
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(src);
bytes.position = 0;
return encodeByteArray(bytes, charSet ? charSet : Base85CharSet.RFC_1924);
}
/**
* 用ByteArray来编码
* @param data 原文的输入流
* @param charSet Base85字符集,默认为 Base85CharSet.RFC_1924
* @return 密文(原文编码后的数据)
*
* @see Base85CharSet#RFC_1924
*/
public static function encodeByteArray(data:IDataInput, charSet:Array = null):String {
charSet = charSet ? charSet : Base85CharSet.RFC_1924;
// Initialise output
var output:String = ""; //output
var srcLength:int = data.bytesAvailable; //length of normal bytes
var endbytes:int = srcLength % 4; //length of extra bytes.
var buf:uint; //encode buffer
//set this var to correct value.(normal = all - extra)
srcLength -= endbytes;
//encode normal group of bytes
for(var i:int = 0; i < srcLength; i+=4) {
buf = data.readUnsignedInt();
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
}
//encode last group of bytes
buf = 0;
for(var j:int = 0; j < endbytes; j++) {
buf = (buf << 8) | data.readByte();
}
switch(endbytes) {
case 0: //no extra byte
break;
case 3: //has 3 extra bytes
output += charSet[buf % 85];
buf /= 85;
case 2: //has 2 extra bytes
output += charSet[buf % 85];
buf /= 85;
default: //has 1 extra byte
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
}
return output;
}
}
}Base85Decoder.as
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package advancedflex.io.format {
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.utils.IDataOutput;
/**
* Base85的解码器
* <p>他把5个字节的文本数据4转换为个字节的2进制数据。</p>
* @see Base85CharSet
* @see Base85Encoder
*/
public class Base85Decoder {
/**
* 解码为String
*
* @param src 密文
* @param charSet 逆字符集
* @return 原文
*
* @see Base85CharSet#RFC_1924
* @see Base85Encoder#encode
*/
public static function decode(src:String, charSet:Object = null):String {
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(src);
var mark:int = bytes.length;
decodeByteArray(src, bytes, charSet ? charSet : Base85CharSet.RFC_1924);
bytes.position = mark;
return bytes.readUTFBytes(bytes.bytesAvailable);
}
/**
* 解码为ByteArray
*
* @param data 密文
* @param output 输出流
* @param decharSet 逆字符集
*
* @see Base85CharSet#RFC_1924
* @see Base85Encoder#encodeByteArray
*/
public static function decodeByteArray(data:String, output:IDataOutput,
decharSet:Object = null):void {
decharSet = decharSet ? decharSet : Base85CharSet.DECODE_RFC_1924;
var dataLength:int = data.length;
var endbytes:int = dataLength % 5;
dataLength -= endbytes;
//decode normal group of bytes
for(var i:int = 0; i< dataLength;i++) {
output.writeUnsignedInt(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85) +
decharSet[data.charAt(++i)]*(85*85*85) +
decharSet[data.charAt(++i)]*(85*85*85*85)
);
}
//decode last group of bytes
var buf:int;
switch(endbytes) {
case 0:
break;
case 4:
buf =
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85) +
decharSet[data.charAt(++i)]*(85*85*85)
);
if(output.endian == Endian.BIG_ENDIAN) {
output.writeByte(
(buf&0xFF0000) >> 16
);
output.writeByte(
(buf&0x00FF00) >> 8
);
output.writeByte(
(buf&0x0000FF)
);
} else {
output.writeByte(
(buf&0x0000FF)
);
output.writeByte(
(buf&0x00FF00) >> 8
);
output.writeByte(
(buf&0xFF0000) >> 16
);
}
break;
case 3:
output.writeShort(
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85)
)
);
break;
default: //2
/* buf =
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85
); */
output.writeByte(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85
);
break;
}
}
}
}
本文来源于 冰山上的播客 http://xinsync.xju.edu.cn , 原文地址:http://xinsync.xju.edu.cn/index.php/archives/183