5.6.2 Commons Codec

在开源组织中,尤其是Java开源组织中,Apache总能为我们提供各种便利的组件包,使我们的开发工作如虎添翼。Apache提供了用于编码转换的组件包Commons Codec,它遵循RFC 2045的相关定义,实现了Base64算法,同时也支持了一般Base64算法的实现。

Commons Codec中用于Base64算法的实现是Base64类,请读者朋友查看第4章相关内容。

我们不改变上一小节中对于Base64Coder类的方法定义,只替换对应方法中的代码实现,完成简单的Base64算法实现。

这里请读者朋友注意使用Base64类的静态方法encodeBase64(),它有多种方法重载,可根据参数决定是否执行RFC 2045标准。

如使用以下方法,将完成一般Base64编码:


//以字节数组返回Base64编码结果。

public static byte[]encodeBase64(byte[]binaryData)

如果使用以下方法,同时将参数isChunked置为true,将按RFC 2045标准执行:

/以字节数组形式返回Base64编码结果,对输出结果中每76个字符追加一个回车换行符。/

public static byte[]encodeBase64(byte[]binaryData, boolean isChunked)


接下来我们改用Commons Codec的Base64算法的相应实现,如代码清单5-3所示。

代码清单5-3 Base64组件2


import org.apache.commons.codec.binary.Base64;

/**

*Base64组件

*@author梁栋

*@version 1.0

*@since 1.0

*/

public abstract class Base64Coder{

//字符编码

public final static String ENCODING="UTF-8";

/**

*Base64编码

*@param data待编码数据

*@return String编码数据

*@throws Exception

*/

public static String encode(String data)throws Exception{

//执行编码

byte[]b=Base64.encodeBase64(data.getBytes(ENCODING));

return new String(b, ENCODING);

}

/**

*Base64安全编码<br>

*遵循RFC 2045实现

*@param data待编码数据

*@return String编码数据

*@throws Exception

*/

public static String encodeSafe(String data)throws Exception{

//执行编码

byte[]b=Base64.encodeBase64(data.getBytes(ENCODING),true);

return new String(b, ENCODING);

}

/**

*Base64解码

*@param data待解码数据

*@return String解码数据

*@throws Exception

*/

public static String decode(String data)throws Exception{

//执行解码

byte[]b=Base64.decodeBase64(data.getBytes(ENCODING));

return new String(b, ENCODING);

}

}


这里对于编码操作实现了2个方法,一个方法用于一般Base64编码实现(encode()方法),另一个用于RFC 2045标准的Base64编码实现(encodeSafe()方法)。

对于解码操作,Commons Codec的Base64类仅需要同一个方法来处理,我们在这里对其包装构造了decode()方法。

对于上述算法实现,给出相应的测试用例,如代码清单5-4所示。

代码清单5-4 Base64组件2测试用例


import static org.junit.Assert.*;

import org.junit.Test;

/**

*Base64编码与解码测试类

*@author梁栋

*@version 1.0

*@since 1.0

*/

public class Base64CoderTest{

//测试Base64编码与解码

@Test

public final void test()throws Exception{

String inputStr="Java加密与解密的艺术";

System.err.println("原文:\t"+inputStr);

//进行Base64编码

String code=Base64Coder.encode(inputStr);

System.err.println("编码后:\t"+code);

//进行Base64解码

String outputStr=Base64Coder.decode(code);

System.err.println("解码后:\t"+outputStr);

//验证Base64编码解码一致性

assertEquals(inputStr, outputStr);

}

//测试Base64编码与解码

@Test

public final void testSafe()throws Exception{

String inputStr="Java加密与解密的艺术";

System.err.println("原文:\t"+inputStr);

//进行Base64编码

String code=Base64Coder.encodeSafe(inputStr);

System.err.println("编码后:\t"+code);

//进行Base64解码

String outputStr=Base64Coder.decode(code);

System.err.println("解码后:\t"+outputStr);

//验证Base64编码解码一致性

assertEquals(inputStr, outputStr);

}

}


我们分别执行两个测试方法。通过执行test()方法,在控制台中获得如下信息:


原文:Java加密与解密的艺术

编码后:SmF2YeWKoOWvhuS4juino+WvhueahOiJuuacrw==

解码后:Java加密与解密的艺术


观察Debug信息,如图5-3所示。

figure_0156_0030

图 5-3 Base64 Debug 2

注意图中字符串变量code的值,我们确定Base64Coder类的encode()方法仅实现了一般Base64编码操作。

我们再来执行testSafe()方法,在控制台中获得如下信息:


原文:Java加密与解密的艺术

编码后:SmF2YeWKoOWvhuS4juino+WvhueahOiJuuacrw==

解码后:Java加密与解密的艺术


这里有个换行,我们很难断定是否还有回车换行符。通过图5-4,我们得到了验证。

注意图中字符串变量code的值,我们明显看到这里有一个回车换行符(“\r\n”)。我们确定Base64Coder类的encodeSafe()方法遵照RFC 2045定义实现了Base64编码操作。

figure_0157_0031

图 5-4 Base64 Debug 3

注意 根据RFC 2045定义,每行为76个字符,行末加入一个回车换行符。但并不是当每行够了76个字符才需要在行末加入一个回车换行符,每行不管够不够76个字符都要加入一个回车换行符。