`
chhj_292
  • 浏览: 37549 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

base64编码原理,实现方式,全解。

阅读更多
package com.******.framework.util.encrpytion;

/**
 * 
 * @author 
 * @version 
 */
public final class Base64 implements IEncrypt {
	/**
	 * 标准base64编码表
	 */
	private final static String	CODEC	= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	private final static Base64	base64	= new Base64();

	private Base64() {

	}

	public static Base64 getInstance() {
		return base64;
	}

	/* (non-Javadoc)
	 * @see com.pantosoft.framework.util.encrpytion.IEncryptencrypt(java.lang.String)
	 */
	public String encrypt(String s) throws Exception {
		return encode(s.getBytes());
	}

	/* (non-Javadoc)
	 * @see com.pantosoft.framework.util.encrpytion.IEncrypt#decrypt(java.lang.String)
	 */
	public String decrypt(String s) throws Exception {
		return new String(this.decode(s));
	}

	private String encode(byte[] bytes) {
		StringBuilder s = new StringBuilder();
		int i = 0;
		byte pos;
		/*
		 一次处理3个字节,3*8 == 4*6 的运算规则来进行重新编码
		 
		 该方法中的*&63,*&15,*&3操作的意义如下:
		 计算机中byte数据类型存储的64形式如下:11111111
		 计算机中byte数据类型存储的15形式如下:1111,即 2^3 + 2^2 + 2^1 + 2^0 = 15
		 “&”、“与”,运算这里主要进行高位清零操作。
		 */
		for (i = 0; i < (bytes.length - (bytes.length % 3)); i += 3) {

			//第一个字节,根据源字节的第一个字节处理。
			//规则:源第一字节右移两位,去掉低2位,高2位补零。
			//既:00 + 高6位
			pos = (byte) ((bytes[i] >> 2) & 63);
			s.append(CODEC.charAt(pos));

			//第二个字节,根据源字节的第一个字节和第二个字节联合处理。
			//规则如下,第一个字节高6位去掉左移四位,第二个字节右移四位
			//即:源第一字节低2位 + 源第2字节高4位
			pos = (byte) (((bytes[i] & 3) << 4) + ((bytes[i + 1] >> 4) & 15));
			s.append(CODEC.charAt(pos));

			//第三个字节,根据源字节的第二个字节和第三个字节联合处理,
			//规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可
			pos = (byte) (((bytes[i + 1] & 15) << 2) + ((bytes[i + 2] >> 6) & 3));
			s.append(CODEC.charAt(pos));

			//第四个字节,规则,源第三字节去掉高2位即可
			pos = (byte) (((bytes[i + 2]) & 63));
			s.append(CODEC.charAt(pos));

			//根据base64的编码规则,每76个字符需要一个换行
			//76*3/4 = 57
			if (((i + 2) % 56) == 0) {
				s.append("\r\n");
			}
		}

		if (bytes.length % 3 != 0) {

			if (bytes.length % 3 == 2) {

				pos = (byte) ((bytes[i] >> 2) & 63);
				s.append(CODEC.charAt(pos));

				pos = (byte) (((bytes[i] & 3) << 4) + ((bytes[i + 1] >> 4) & 15));
				s.append(CODEC.charAt(pos));

				pos = (byte) ((bytes[i + 1] & 15) << 2);
				s.append(CODEC.charAt(pos));

				s.append("=");

			} else if (bytes.length % 3 == 1) {
				//分出第一个二进制位的前6位,右移两位,得到一个新8位
				pos = (byte) ((bytes[i] >> 2) & 63);
				s.append(CODEC.charAt(pos));
				//先清零比3高的高位,分出8位的后两位,然后左移4位,得到一个新8位
				pos = (byte) ((bytes[i] & 3) << 4);
				s.append(CODEC.charAt(pos));

				s.append("==");
			}
		}
		return s.toString();
	}

	/**
	 * 
	 * @param s
	 * @return
	 * @throws Exception
	 */
	public byte[] decode(String s) throws Exception {
		StringBuffer buf = new StringBuffer(s);
		int i = 0;
		char c = ' ';
		char oc = ' ';
		while (i < buf.length()) {
			oc = c;
			c = buf.charAt(i);
			if (oc == '\r' && c == '\n') {
				buf.deleteCharAt(i);
				buf.deleteCharAt(i - 1);
				i -= 2;
			} else if (c == '\t') {
				buf.deleteCharAt(i);
				i--;
			} else if (c == ' ') {
				i--;
			}
			i++;
		}

		//base64编码的字符长度必须为4的倍数   
		if (buf.length() % 4 != 0) {
			throw new Exception("Base64 decoding invalid length");
		}

		//预设的字节数组的长度
		byte[] bytes = new byte[3 * (buf.length() / 4)];
		int index = 0;

		/**
		 * 每4个base64字符代表一个源字符编码后的字符!
		 * 
		 * 然后每四个字符分别做循环,每个循环左移6位,作为低6位,该低6位再补上下一个base64字符在base64码表中的序列。
		 * 因为字符在码表中的序列小于等于64,即,小于等于2的6次方(6位)!
		 */
		for (i = 0; i < buf.length(); i += 4) {

			byte base64Index = 0;
			int nGroup = 0;

			for (int j = 0; j < 4; j++) {

				char theChar = buf.charAt(i + j);

				if (theChar == '=') {
					base64Index = 0;
				} else {
					base64Index = getBase64Index(theChar);
				}

				if (base64Index == -1) {
					throw new Exception("Base64 decoding bad character");
				}
				//每次都想高位移动6个位置后再加上新的字符所在base64编码表中的位置。
				nGroup = (nGroup << 6) + base64Index;
			}

			//右移16位,取高8位
			bytes[index] = (byte) (255 & (nGroup >> 16));
			index++;

			//右移8位,取高16位,且与00..0011111111(32位windows系统)进行and操作,取该高16位的低8位。
			if ((255 & (nGroup >> 8)) == 0) {
				continue;
			}
			bytes[index] = (byte) (255 & (nGroup >> 8));
			index++;

			//直接与00..0011111111进行and操作,该32位数的低8位
			if ((255 & nGroup) == 0) {
				continue;
			}
			bytes[index] = (byte) (255 & (nGroup));
			index++;
		}

		byte[] newBytes = new byte[index];
		for (i = 0; i < index; i++) {
			newBytes[i] = bytes[i];
		}

		return newBytes;
	}

	/**
	 * 从编码表中找出对应的字符序列
	 * @param c
	 * @return
	 */
	private byte getBase64Index(char c) {
		byte index = -1;
		for (byte i = 0, j = (byte) (CODEC.length() & 225); i < j; i++) {
			if (CODEC.charAt(i) == c) {
				index = i;
				break;
			}
		}
		return index;
	}

	static final char	digits[]	= { '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'				};

	private static String toUnsignedString(int i, int j) {
		char ac[] = new char[32];
		int k = 32;
		int l = 1 << j;
		int i1 = l - 1;
		do {
			ac[--k] = digits[i & i1];
			i >>>= j;
		} while (i != 0);
		return new String(ac, k, 32 - k);
	}

	public static void main(String[] args) {

		String encodedString = null;
		String s = "	linux  和	windows下默认使用firefox下载文件的时侯,rar文件会自动被firefox下载后显示为一堆";

		byte[] bytes = s.getBytes();
		for (int i = 0; i < bytes.length; i++) {
			String s1 = toUnsignedString(bytes[i], 1);
			if (s1.length() >= 24)
				System.out.println(s1 + "," + s1.substring(24, s1.length()));
		}

		try {
			encodedString = Base64.getInstance().encrypt(s);
			System.out.println("加密:" + encodedString);
			System.out.println("解密:"
					+ Base64.getInstance().decrypt(encodedString));
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

 

我一直用js的base64和java的base64来处理中文问题。

 

 

类似的方式还有window.escapse("")和强制转型的方式!

	private char unescape(String _str) throws NumberFormatException {
		return ((char) Integer.valueOf(_str, 16).intValue());
	}

两种方法原理类似,都在在客户端使用一种可还原的编码方式对字符进行编码,在服务器进行解码的方式处理!

 

 

 

分享到:
评论
3 楼 chhj_292 2010-01-21  
asialee 写道
你好,我对base64编码的原理不是很懂,您有时间的话能不能介绍一下编码的原理。

你可以详细看下代码的注释。
2 楼 chhj_292 2010-01-21  
一个字节是8位。1byte == 8bits,3个字节就是24位。base64的原理就是一次处理3个字节,根据3*8 == 4*6的运算规则来进行重新编码。原来的3个字节扩容变成了4个字节,然后根据这4个字节的实际数在编码表中找到对应的字符组合起来。
11111111,11111111,11111111
00111111,00111111,00111111,00111111
高2位都补0,所以其有效位置只有低6位。
1 楼 asialee 2010-01-19  
你好,我对base64编码的原理不是很懂,您有时间的话能不能介绍一下编码的原理。

相关推荐

    labview 图片缩放 base64编码base64解码

    同时,理解Base64编码的基本原理也是必要的,这将帮助你正确地进行编码和解码操作,确保数据的完整性和一致性。 在提供的压缩包文件“图片缩放编码解码”中,很可能包含了实现这些功能的LabVIEW程序或范例。你可以...

    易语言汇编base64编码

    Base64编码是一种在网络上传输二进制数据时常用的数据编码方式,它将任意二进制数据转化为可打印的ASCII字符,方便在网络协议如电子邮件中传输。 Base64编码的基本原理是将每3个8位字节(24位)的数据转换成4个6位...

    Base64编码原理及base64函数

    Base64编码原理及base64函数 Base64编码是一种常用的将二进制数据转换为可打印字符的编码,占用空间较小。在RFC 3548中定义。Base64编码的原理是将数据编码成24bit的二进制数,然后将其分成四组,每组6bit,对应于...

    Base64.zip_labview base64

    下面我们将详细探讨如何在LabVIEW中实现Base64编码以及这个VI可能的工作原理。 1. **Base64编码原理**: - Base64编码基于64个可打印的ASCII字符,包括大小写字母、数字以及"+"和"/",还有在末尾可能会出现的等于...

    Base64编码解码工具成品+源码

    Base64编码是一种在网络上传输二进制数据的文本编码方式,主要应用于电子邮件、网页编码等领域,确保数据在传输过程中的安全性和可读性。它将任意二进制数据转换成可打印的ASCII字符,避免了非ASCII字符在传输过程中...

    Base64编码解码工具

    **Base64编码原理:** Base64编码基于64个字符的字符集,这个字符集包括26个小写字母、26个大写字母、10个数字以及两个特殊字符“+”和“/”。每个64个字符代表一个6位的二进制数,这意味着每个64字符可以表示2^6 = ...

    java和js相互base64编码解码

    总之,Java和JavaScript中Base64编码和解码的实现原理相似,都是将二进制数据转换为可打印的ASCII字符。Java自Java 8开始内置了Base64支持,而JavaScript则依赖于`btoa()`和`atob()`函数,或者使用第三方库。在实际...

    C语言base64编码解码库

    在IT领域,Base64是一种常见的编码方式,用于将二进制数据转化为可以在电子邮件系统、文本文件等中安全传输的ASCII字符串。C语言是编程语言的基础,被广泛应用于系统编程和嵌入式开发,因此一个C语言实现的Base64...

    易语言 base64编码转图片 如何 提高转换速度.zip

    在IT行业中,Base64编码是一种常见的数据编码方式,它将二进制数据转化为可打印的ASCII字符,常用于在网络上传输图片、音频或视频等非文本数据。易语言作为一款中国本土化的编程语言,提供了处理Base64编码的功能。...

    Base64编码解码工具V1.5

    Base64编码的主要原理是将每3个8位字节(24位)的数据分成4个6位组(每个6位可以表示0-63的十进制数),然后将这些数值映射到Base64字符集中。如果原始数据不是3的倍数,那么会在末尾添加0字节,直到长度达到3的倍数...

    base64编码解码离线工具

    Base64编码是一种在网络上传输二进制数据时常用的编码方式,它将任意二进制数据转换成可打印的ASCII字符序列。这种编码方法最初是为了在电子邮件系统中传输非ASCII字符而设计的,如今在很多场景下都有应用,如图片...

    Base64编码jar包

    `javabase64-1.3.1.jar`可能提供了这种编码方式,具体实现取决于库的API。 注意,虽然这里介绍的是`javabase64-1.3.1.jar`库,但Java 8及更高版本已经内置了`java.util.Base64`类,提供了一套标准的Base64编码和...

    易语言API实现BASE64编码

    BASE64是一种常见的数据编码方式,主要用于将二进制数据转化为可打印的ASCII字符,以便在网络上传输或者存储。它的基本原理是将每3个字节的数据转化为4个6位的十六进制字符,不足3字节的数据会用零填充,并在结果...

    文件转换为Base64编码

    Base64编码是一种在互联网上常见的数据编码方式,主要用于在不支持二进制传输的环境(如邮件系统)中传输二进制数据。它将任意的二进制数据转化为可打印的ASCII字符序列,以便在文本格式下进行传输和存储。这种编码...

    将图片进行Base64编码后传输

    "将图片进行Base64编码后传输"是一种高效且便捷的方式,它允许我们直接将图片数据嵌入到文本格式中,方便在网络中传递。这种技术广泛应用于JSON API、HTML页面以及任何不支持二进制数据流的系统。 Base64是一种编码...

    Base64系列第四篇 C/C++中使用Base64编码解码(从chromium库中抽取)

    首先,Base64编码的原理是将每3个字节(24位)的数据转换为4个6位的字符,然后将这4个6位字符对应到Base64的字符集(包括大小写字母、数字和两个特殊符号`+`和`/`)。对于不足3字节的数据,会在编码前补足0,以保证...

    Base64编码(VC++实现)

    Base64编码是一种广泛使用的数据编码方式,尤其在互联网通信和电子邮件系统中尤为常见。它主要目的是将二进制数据转换成ASCII字符形式,以便在只支持文本的传输通道中安全地传递。在VC++环境下实现Base64编码,我们...

    .NET 中实现 Base64 编码

    首先,我们来详细了解一下Base64编码的基本原理。Base64编码是通过将每3个8位字节的数据转换为4个6位的字节,并将这4个6位字节转换为64个可能字符中的一个。因为ASCII码有64个可打印字符(不包括换行符和控制字符)...

Global site tag (gtag.js) - Google Analytics