Java:Base64 编解码

同系列文章:

/* ----------------------------------------------------------
 * 文件名称:Base64.java
 * 
 * 作者:秦建辉
 * 
 * MSN:splashcn@msn.com
 * QQ:36748897
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *     Eclipse Juno
 *     Java SE 7u5
 *     
 * 版本历史:
 *      V1.1    2012年08月19日
 *              改进解码算法,字符串中允许任意的空白字符、回车换行符、连字符
 *              
 *      V1.0	2012年05月30日
 *              Base64编解码
 *              
 * 参考资料:
 * 		http://www.openssl.org/
------------------------------------------------------------ */

package com.firstsolver.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class Base64
{
	private final static String DATA_BIN2ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	
	// 将字节数组转换成Base64编码字符串
	public static String encodeBase64String(byte[] binaryData)
	{
		if(binaryData == null) return null;
		
		// 每3个字节转换成4个字符
		int Length = ((binaryData.length + 2) / 3) << 2;
		StringBuilder sb = new StringBuilder(Length);
		
		int Index = 0;
		for(int i = binaryData.length; i > 0; i -= 3)
		{		
			if(i >= 3)
			{	// 将3字节数据转换成4个ASCII字符
				int b0 = binaryData[Index++] & 0xFF;
				int b1 = binaryData[Index++] & 0xFF;
				int b2 = binaryData[Index++] & 0xFF;
				
				sb.append(DATA_BIN2ASCII.charAt(b0 >> 2));
				sb.append(DATA_BIN2ASCII.charAt(((b0 << 4) | (b1 >> 4)) & 0x3F));
				sb.append(DATA_BIN2ASCII.charAt(((b1 << 2) | (b2 >> 6)) & 0x3F));
				sb.append(DATA_BIN2ASCII.charAt(b2 & 0x3F));
			}
			else
			{
				int b0 = binaryData[Index++] & 0xFF;
				int b1;
				if(i == 2)
					b1 = binaryData[Index++] & 0xFF;
				else
					b1 = 0;
				
				sb.append(DATA_BIN2ASCII.charAt(b0 >> 2));
				sb.append(DATA_BIN2ASCII.charAt(((b0 << 4) | (b1 >> 4)) & 0x3F));
				if(i == 1)
					sb.append('=');
				else
					sb.append(DATA_BIN2ASCII.charAt((b1 << 2) & 0x3F));
				sb.append('=');
			}
		}
		
		return sb.toString();
	}
	
	// private final static int B64_ERROR = -1;		// 0xFF 错误字符
	// private final static int B64_EOLN = -16;		// 0xF0 换行\n
	// private final static int B64_CR = -15;		// 0xF1 回车\r
	// private final static int B64_EOF = -14;		// 0xF2 连字符-		
	// private final static int B64_WS = -32;		// 0xE0 跳格或者空格(\t、space)
	private final static int B64_NOT_BASE64 = -13;	// 0xF3 空白字符、回车换行字符、连字符
	
	private final static byte[] DATA_ASCII2BIN = {
		  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, -32, -16,  -1,  -1, -15,  -1,  -1,
		  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
		 -32,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,0x3E,  -1, -14,  -1,0x3F,
		0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,  -1,  -1,  -1,0x00,  -1,  -1,
		  -1,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
		0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,  -1,  -1,  -1,  -1,  -1,
		  -1,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
		0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,  -1,  -1,  -1,  -1,  -1
	};

	// 将Base64编码字符串复原为字节数组。字符串中允许任意的空白字符、回车换行符、连字符
	public static byte[] decodeBase64(String base64String)
			throws IOException
	{
		if(base64String == null || base64String.isEmpty())
			return null;	
		
		ByteArrayOutputStream memoryStream = null;
		try
		{
			int length = base64String.length();
			memoryStream = new ByteArrayOutputStream(((length + 3) >> 2) * 3);
			
			int index = 0;
			int previous = 0;
			for(int i = 0; i < length; i++)
			{
				int charValue = base64String.charAt(i);
				if(charValue >= 0x80)
					throw new IllegalArgumentException();	// 错误字符			
				
				int orderValue = DATA_ASCII2BIN[charValue];
				if(orderValue == -1)
					throw new IllegalArgumentException();	// 错误字符
				
				// 跳过空白字符、回车换行字符、连字符
				if((orderValue | 0x13) == B64_NOT_BASE64)
					continue;					
				
				if(index == 0)
				{
					if(charValue == '=')
						throw new IllegalArgumentException();
					
					previous = orderValue;
					index++;
				}
				else if(index == 1)
				{
					if(charValue == '=')
						throw new IllegalArgumentException();
					
					memoryStream.write((previous << 2) | (orderValue >> 4));
					previous = orderValue;
					index++;					
				}
				else if(index == 2)
				{
					if(charValue == '=')
					{	// 简化处理,不再判断第二个'='
						index = 0;
						break;
					}
					
					memoryStream.write((previous << 4) | (orderValue >> 2));
					previous = orderValue;
					index++;
				}
				else
				{
					index = 0;
					if(charValue == '=')break;
					
					memoryStream.write((previous << 6) | orderValue);					
				}
			} // End for
			
			// 有效字符个数必须是4的倍数
			if(index == 0)
				return memoryStream.toByteArray();
			else
				throw new IllegalArgumentException();
		}
		finally
		{
			if(memoryStream != null) memoryStream.close();
		}
	}
}

Comments are closed.