All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net_io.utils.EncodeUtils Maven / Gradle / Ivy

The newest version!
/**
 * 常用编码解码类
 * 
 * 
 * 
 * 64编码:
 *    字节:1      2      3
 *    原码:8      16     24
 *    编码:2(4)   3(2)   4
 * 
 * 32编码:
 *    字节:1      2      3      4      5 
 *    原码:8      16     24     32     40
 *    编码:2(3)   4(1)   5(1)   7(3)   8
 * 
 * @author Hansen
 */
package net_io.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class EncodeUtils {

	/** 支持http协议的62进制编码 **/
	private static byte[] myBase62EncodeMap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".getBytes(Charsets.ISO_8859_1);
	private static final byte[] myBase62DecodeMap = new byte[256];
	private static final long[] myBase62Mode = {1L, 62L, 62L*62L, 62L*62L*62L, 62L*62L*62L*62L, 62L*62L*62L*62L*62L, 62L*62L*62L*62L*62L*62L};
	/** 支持http协议的64进制编码 **/
	private static byte[] encodeHttp64Map = "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".getBytes(Charsets.ISO_8859_1);
	private static final byte[] decodeHttp64Map = new byte[127];
	/** 支持http协议的32进制编码 **/
	private static byte[] encodeHttp32Map = "0123456789abcdefghjkmnpqrstuvxyz".getBytes(Charsets.ISO_8859_1);
	private static final byte[] decodeHttp32Map = new byte[127];
	/** 标准base64编码 **/
	private static byte[] encodeBase64Map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(Charsets.ISO_8859_1);
	private static final byte[] decodeBase64Map = new byte[127];
	private static final byte base64BackfillChar = '=';
	/** bit位掩码 **/
	private static int[] bitMask = {0, 1, 3, 7, 15, 31, 63, 127};
	/** long型1字节未掩码 **/
	private static final long MASK_1_BYTE_LONG = 0xFFL;
	/** 自增量 **/
	private static AtomicLong autoIncrement = new AtomicLong(0);


	static {
		//32进制编码
		for(int i=0; i> queues = new HashMap>();
	
	
	private EncodeUtils() {
		// Hide default constructor for this utility class
	}
	
	static {
		try {
			// Init commonly used algorithms
			init(MD5);
			init(SHA1);
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalArgumentException(e);
		}
	}

	/**
	 * 检查类是否存在(不初始化类的静态属性)
	 */
	public static boolean isClassExist(String className) {
		try {
			Thread.currentThread().getContextClassLoader().loadClass(className);
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	
	/**
	 * 预知可靠byte[]数据流量,按UTF-8编码转换为String
	 */
	public static String toStringUTF8(byte[] bts) {
		if(bts == null) return null;
		return new String(bts, Charsets.UTF_8);
	}

//	/**
//	 * 预知可靠String类型,按UTF-8编码转换为byte[]数据流
//	 */
//	public static byte[] toBytesUTF8(String str) {
//		if(str == null) return null;
//		return str.getBytes(CHARSETS.UTF_8);
//	}

	/**
	 * int类型转换为byte[]类型(高位在前)
	 */
	public static int bytesToInt(byte[] buff, int offset) {
		int loopEnd = Math.min(buff.length, offset+4);
		int moveBit = (loopEnd - offset - 1) * 8;
		int ret = 0;
		for(int i=offset; i>> moveBit) & 0xFF); 
			moveBit -= 8;
		}
	}
	
	/**
	 * 创建内含时间戳的随机字符串。16字节,96位空间,支持不编码http协议传输
	 */
	public static String createTimeRandId() {
		long time = System.currentTimeMillis();
		int[] ret = new int[3];
		ret[0] = (int)(time / 1000);
		long num1 = time % 1000; //毫秒
		long num2 = autoIncrement.incrementAndGet() & 0x3FF;
		long num3 = System.nanoTime() & 0x3FF;
		ret[1] = (int)num1 << 22; //1 ~ 10 bit
		ret[1] |= (int)num2 << 10;
		ret[1] |= (int)num3;
		long num4 = Math.round(Math.random() * 0x100000000L);
		ret[2] = (int)num4;
		byte[] buff = new byte[12];
		intToBytes(ret[0], buff, 0);
		intToBytes(ret[1], buff, 4);
		intToBytes(ret[2], buff, 8);
		return toStringUTF8(encodeHttp64(buff));
	}
	
	public static long parseRandTime(String randId) {
		if(randId == null) {
			return 0;
		}
		int[] ret = new int[2];
		byte[] buff = decodeHttp64(randId.getBytes(Charsets.UTF_8));
		ret[0] = EncodeUtils.bytesToInt(buff, 0);
		ret[1] = EncodeUtils.bytesToInt(buff, 4);
		long time = ((long)ret[0] & 0xFFFFFFFFL) * 1000;
		time += (ret[1] >>> 22) & 0x3FF;
		return time;
	}

	/** 随机数填充 **/
	public static void fillRandomNumber(byte[] bts) {
		if(bts == null) {
			return;
		}
		int randNum = (int)(Math.random() * Integer.MAX_VALUE);
		for(int i=0; i= 'a' && firstChar <= 'z') {
			firstChar -= 32;
			return firstChar + str.substring(1);
		} else {
			return str;
		}
	}

	/**
	 * 转换字符串为首字母小写
	 * @param str 源字符
	 * @return 若字符串以英文单词开头则返回首字母小写,否则返回源字符串
	 */
	public static String stringLowerFirst(String str) {
		if (str == null || str.length() == 0) {
			return str;
		}
		char firstChar = str.charAt(0);
		if (firstChar >= 'A' && firstChar <= 'Z') {
			firstChar += 32;
			return firstChar + str.substring(1);
		} else {
			return str;
		}
	}

	/**
	 * 按62进制编码(编码率:7/5)
	 * @param bts 二进制数组
	 * @return 编码字符范围:0-9A-Za-z
	 */
	public static String myBase62Encode(byte[] bts) {
		if(bts == null) {
			return null;
		}
		int mode = bts.length % 5;
		if(mode >= 3) {
			mode += 2;
		} else if(mode >= 1) {
			mode++;
		}
		byte[] buff = new byte[bts.length / 5 * 7 + mode];
		int offset = 0;
		for(int loop=0; loop 5) {
				byteCount = 5;
			}
			int modeOffset = byteCount;
			if(byteCount >= 3) {
				modeOffset += 2;
			} else {
				modeOffset++;
			}
			int moveBit = (byteCount - 1) * 8;
			long num = 0;
			for(int i=loop; i= 0; i++) {
				num |= (bts[i] & MASK_1_BYTE_LONG) << moveBit;
				moveBit -= 8;
			}
			for(int i=1; i= 5) {
			mode -= 2;
		} else if(mode >= 1) {
			mode--;
		}
		byte[] buff = new byte[bts.length / 7 * 5 + mode];
		int offset = 0;
		for(int loop=0; loop 7) {
				byteCount = 7;
			}
			long num = 0;
			for(int i=0; i= 0) {
					num += chNum * myBase62Mode[byteCount - i - 1];
				} else {
					//TODO
				}
			}
			int modeOffset = byteCount;
			if(byteCount >= 5) {
				modeOffset -= 2;
			} else {
				modeOffset--;
			}
			int moveBit = (modeOffset - 1) * 8;
			for(; moveBit>=0; moveBit-=8) {
				buff[offset++] = (byte) ((num >>> moveBit) & MASK_1_BYTE_LONG);
			}
		}
		return buff;
	}

	/** 支持HTTP协议的base64编码(字符升序,扩展字符用用".-"代替) **/
	public static byte[] encodeHttp64(byte[] bts) {
		return _encodeBase64(encodeHttp64Map, bts, false);
	}

	/** 支持HTTP协议的base64编码(字符升序,扩展字符用用".-"代替)**/
	public static String encodeHttp64ToString(byte[] bts) {
		bts = _encodeBase64(encodeHttp64Map, bts, false);
		if(bts == null) {
			return null;
		}
		return new String(bts, Charsets.US_ASCII);
	}

	/** base64解码(字符升序,扩展字符用用".-"代替) **/
	public static byte[] decodeHttp64(byte[] bts) {
		return _decodeBase64(decodeHttp64Map, bts, false);
	}

	/** base64解码(字符升序,扩展字符用用".-"代替) **/
	public static byte[] decodeHttp64(String str) {
		if(str == null) {
			return null;
		}
		return _decodeBase64(decodeHttp64Map, str.getBytes(Charsets.US_ASCII), false);
	}

	/** base64编码 **/
	public static byte[] encodeBase64(byte[] bts) {
		return _encodeBase64(encodeBase64Map, bts, true);
	}

	/** base64编码 **/
	public static String encodeBase64ToString(byte[] bts) {
		bts = _encodeBase64(encodeBase64Map, bts, true);
		if(bts == null) {
			return null;
		}
		return new String(bts, Charsets.US_ASCII);
	}

	/** base64解码 **/
	public static byte[] decodeBase64(byte[] bts) {
		return _decodeBase64(decodeBase64Map, bts, true);
	}

	/** base64解码 **/
	public static byte[] decodeBase64(String str) {
		if (str == null) {
			return null;
		}
		return _decodeBase64(decodeBase64Map, str.getBytes(Charsets.US_ASCII), true);
	}

	/**
	 * 转换bigint为12字节的字符串
	 * @param bts 待编码数据
	 * @return string
	 */
	public static byte[] encodeHttp32(byte[] bts) {
		if(bts == null) {
			return null;
		}
		int buffSize = bts.length * 8 / 5;
		if(bts.length * 8 % 5 > 0) {
			buffSize++;
		}
		int offset = 0;
		byte[] buff = new byte[buffSize];
		int prevBitCount = 0;
		int prevBitNum = 0;
		for(int i=0; i>> nextBitCount) & bitMask[8-nextBitCount];
			if(prevBitCount > 0) {
				numIndex |= (byte)(prevBitNum << (5 - prevBitCount));
			}
			buff[offset++] = encodeHttp32Map[numIndex];
			if(nextBitCount > 5) {
				numIndex = (nextBitNum >>> (nextBitCount-5)) & bitMask[7];
				buff[offset++] = encodeHttp32Map[numIndex];
				prevBitCount = nextBitCount - 5;
				prevBitNum = nextBitNum & bitMask[prevBitCount];
			} else if(nextBitCount == 5) {
				buff[offset++] = encodeHttp32Map[nextBitNum];
				prevBitCount = 0;
				prevBitNum = 0;
			} else {
				prevBitCount = nextBitCount;
				prevBitNum = nextBitNum;				
			}
		}
		if(prevBitCount > 0) {
			buff[offset++] = encodeHttp32Map[prevBitNum << (5 - prevBitCount)];
		}
		return buff;
	}

	public static byte[] decodeHttp32(byte[] bts) {
		if(bts == null) {
			return null;
		}
		int buffSize = bts.length * 5 / 8;
		int lastPosition = bts.length - 1;
		byte[] buff = new byte[buffSize]; //创建buff
		int offset = 0;
		int prevBitCount = 0;
		for(int i=0; i 0) {
				num = decodeHttp32Map[ch];
			}
			if(prevBitCount == 0) {
				buff[offset] = (byte) (num << 3);
				prevBitCount = 3;
			} else if(prevBitCount > 5) {
				buff[offset] |= (byte) (num << (prevBitCount - 5));
				prevBitCount = prevBitCount - 5;				
			} else if(prevBitCount == 5) {
				buff[offset++] |= (byte)num;
				prevBitCount = 0;
			} else { // 1~4
				buff[offset++] |= (byte) (num >>> (5-prevBitCount));
				if(i < lastPosition) {
					buff[offset] = (byte) ((num & bitMask[5-prevBitCount]) << 3+prevBitCount);
				}
				prevBitCount = 3 + prevBitCount;
			}
		}
		return buff;
	}

	public static byte[] encodeGZIP(byte[] bts) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		GZIPOutputStream gzip = new GZIPOutputStream(out);
		gzip.write(bts);
		gzip.close();
		return out.toByteArray();
	}

	public static byte[] decodeGZIP(byte[] bts) throws IOException {
		GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(bts));
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		byte[] buff = new byte[1024];
		int size;
		while((size = gzip.read(buff)) > 0) {
			out.write(buff, 0, size);
		}
		gzip.close();
		return out.toByteArray();
	}

	/**
	 * 二进制数组,转为16进制表示字符串
	 * @param bts
	 * @return String
	 */
	public static String bin2hex(byte[] bts) {
		if(bts == null) {
			return null;
		}
		char myChar[] = new char[bts.length * 2];
		int k = 0;
		for (int i = 0; i < bts.length; i++) {
			byte byte0 = bts[i];
			myChar[k++] = hexDigits[byte0 >>> 4 & 0x0f];
			myChar[k++] = hexDigits[byte0 & 0x0f];
		}
		return new String(myChar);		
	}
	
	/**
	 * MD5编码
	 * @param str 待加密的字符串(系统默认编码)
	 */
	public static String md5(String str) {
		return md5(str, null);
	}
	/**
	 * MD5编码
	 * @param str 待加密的字符串
	 * @param charset 编码格式
	 */
	public static String md5(String str, String charset) {
		try {
			byte[] bts;
			if(charset != null) {
				bts = str.getBytes(charset);
			} else {
				bts = str.getBytes();
			}
			bts = messageDigest("MD5", bts);
			return bin2hex(bts);
		} catch(Exception e) {
			throw new RuntimeException(e.toString());
		}
	}
	
	/**
	 * SH1编码
	 * @param str 待加密的字符串(系统默认编码)
	 */
	public static String sha1(String str) {
		return sha1(str, null);
	}
	/**
	 * SH1编码
	 * @param str 待加密的字符串
	 * @param charset 编码格式
	 */
	public static String sha1(String str, String charset) {
		try {
			byte[] bts;
			if(charset != null) {
				bts = str.getBytes(charset);
			} else {
				bts = str.getBytes();
			}
			bts = messageDigest("SHA-1", bts);
			return base64Encode(bts);
		} catch(Exception e) {
			throw new RuntimeException(e.toString());
		}
	}

	/**
	 * @deprecated
	 */
	public static String base64Encode(byte[] bts) {
		return encodeBase64ToString(bts);
	}

	/**
	 * @deprecated
	 */
	public static byte[] base64Decode(String str) {
		return decodeBase64(str);
	}

	/** base64编码算法实现 **/
	private static byte[] _encodeBase64(byte[] encodeMap, byte[] bts, boolean backfill) {
		if(bts == null) {
			return null;
		}
		int buffSize = bts.length * 4 / 3;
		int mode = bts.length % 3;
		if(mode > 0) {
			buffSize++;
			if(backfill) {
				if (mode == 1) {
					buffSize += 2;
				} else {
					buffSize++;
				}
			}
		}
		int offset = 0;
		byte[] buff = new byte[buffSize];
		//最后1位或2位,补填充字符“=”
		if(backfill && mode > 0) {
			buff[buffSize-1] = base64BackfillChar;
			if (mode == 1) {
				buff[buffSize - 2] = base64BackfillChar;
			}
		}
		int prevBitCount = 0;
		int prevBitNum = 0;
		for(int i=0; i>> (2 + prevBitCount)) & bitMask[6-prevBitCount];
			index |= prevBitNum << (6 - prevBitCount);
			buff[offset++] = encodeMap[index];
			if(nextBitCount >= 6) {
				buff[offset++] = encodeMap[nextBitNum];
				prevBitCount = 0;
				prevBitNum = 0;
			} else {
				prevBitCount = nextBitCount;
				prevBitNum = nextBitNum;
			}
		}
		if(prevBitCount > 0) {
			if(backfill) { //标准BASE64编码,移至高位
				if (prevBitCount < 6) {
					prevBitNum <<= 6 - prevBitCount;
				}
			}
			buff[offset++] = encodeMap[prevBitNum];
		}
		return buff;
	}

	/** base64解码算法实现 **/
	private static byte[] _decodeBase64(byte[] decodeMap, byte[] bts, boolean backfill) {
		if(bts == null) {
			return null;
		}
		int srcSize = bts.length;
		if(backfill) {
			for(int i=1; i<8 && srcSize > 0; i++) {
				if(bts[srcSize - 1] != base64BackfillChar) {
					break;
				}
				srcSize--;
			}
		}
		int buffSize = srcSize * 3 / 4;
		int mode = srcSize % 4;
		int lastBitCount = 0;
		int lastPosition = srcSize - 1;
		if(mode > 0) {
			if(mode == 3) {
				lastBitCount = 4;
			} else {
				lastBitCount = 2;
			}
		}
		byte[] buff = new byte[buffSize]; //创建buff
		int offset = 0;
		int prevBitCount = 0;
		for(int i=0; i 0) {
				num = decodeMap[ch];
			}
			if(prevBitCount == 0) {
				buff[offset] = (byte) (num << 2);
				prevBitCount = 2;
			} else if(prevBitCount == 6) {
				buff[offset++] |= (byte)num;
				prevBitCount = 0;
			} else if(i == lastPosition && lastBitCount > 0) {
				if(backfill) { //标准BASE64编码
					buff[offset++] |= num >>> (6-lastBitCount) & bitMask[lastBitCount];
				} else {
					buff[offset++] |= num & bitMask[lastBitCount];
				}
			} else {
				buff[offset++] |= (byte) (num >>> (6-prevBitCount));
				buff[offset] = (byte) ((num & bitMask[6-prevBitCount]) << 2+prevBitCount);
				prevBitCount = 2 + prevBitCount;
			}
		}
		return buff;
	}

	private static byte[] messageDigest(String mode, byte[] bts) throws NoSuchAlgorithmException {
		MessageDigest messageDigest = MessageDigest.getInstance(mode);
		messageDigest.update(bts);
		return  messageDigest.digest();
	}
	
	public static byte[] digestMD5(byte[]... input) {
		return digest(MD5, input);
	}
	
	public static byte[] digestSHA1(byte[]... input) {
		return digest(SHA1, input);
	}
	
	private static byte[] digest(String algorithm, byte[]... input) {
		return digest(algorithm, 1, input);
	}
	
	
	private static byte[] digest(String algorithm, int rounds, byte[]... input) {
	
		Queue queue = queues.get(algorithm);
		if (queue == null) {
			throw new IllegalStateException("Must call init() first");
		}
	
		MessageDigest md = queue.poll();
		if (md == null) {
			try {
				md = MessageDigest.getInstance(algorithm);
			} catch (NoSuchAlgorithmException e) {
				// Ignore. Impossible if init() has been successfully called
				// first.
				throw new IllegalStateException("Must call init() first");
			}
		}
	
		// Round 1
		for (byte[] bytes : input) {
			md.update(bytes);
		}
		byte[] result = md.digest();
	
		// Subsequent rounds
		if (rounds > 1) {
			for (int i = 1; i < rounds; i++) {
				md.update(result);
				result = md.digest();
			}
		}
	
		queue.add(md);
	
		return result;
	}
	
	
	/**
	 * Ensures that {@link #digest(String, byte[][])} will support the specified
	 * algorithm. This method must be called and return successfully
	 * before using {@link #digest(String, byte[][])}.
	 *
	 * @param algorithm The message digest algorithm to be supported
	 *
	 * @throws NoSuchAlgorithmException If the algorithm is not supported by the
	 *								  JVM
	 */
	private static void init(String algorithm) throws NoSuchAlgorithmException {
		synchronized (queues) {
			if (!queues.containsKey(algorithm)) {
				MessageDigest md = MessageDigest.getInstance(algorithm);
				Queue queue = new ConcurrentLinkedQueue();
				queue.add(md);
				queues.put(algorithm, queue);
			}
		}
	}

	public static class Charsets {
		/**
		 * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
		 * Unicode character set
		 */
		public static final Charset US_ASCII = Charset.forName("US-ASCII");
		/**
		 * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
		 */
		public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
		/**
		 * Eight-bit UCS Transformation Format
		 */
		public static final Charset UTF_8 = Charset.forName("UTF-8");
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy