package cn.hmsoft.helper;

import java.math.BigInteger;

/****************************************
 * @note 字节相关辅助类
 * @author revisit@126.com
 * @Company: www.hmsoft.cn
 * @create 2017-05-04 15:42:28
 * @version 4.0.0
 */
public abstract class ByteHelper {

	/**************************
	 * 将一个2位字节数组转换为char字符。
	 */
	public static char bytesToChar(byte[] b) {
		char c = (char) ((b[0] << 8) & 0xFF00L);
		c |= (char) (b[1] & 0xFFL);
		return c;
	}

	/*********************************
	 * 将字节数组转换为字符串的方式
	 * b[0] = -26 --> E6
	 */
	public static String byteToHex(byte[] b) {
		if (b == null)
			return "";
		String hs = "";
		String stmp = "";
		for (byte element : b) {
			stmp = Integer.toHexString(element & 0XFF);
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}

	/**
	 * 将一个8位字节数组转换为双精度浮点数。
	 * 注意，函数中不会对字节数组长度进行判断，请自行保证传入参数的正确性。
	 */
	public static double bytesToDouble(byte[] b) {
		return Double.longBitsToDouble(bytesToLong(b));
	}

	/**
	 * 将一个4位字节数组转换为浮点数。
	 */
	public static float bytesToFloat(byte[] b) {
		return Float.intBitsToFloat(bytesToInt(b));
	}

	/**********************************
	 * 将两个ASCII字符合成一个字节；
	 * "EF"--> 0xEF
	 */
	public static byte unitBytes(byte src0, byte src1) {
		byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 })).byteValue();
		_b0 = (byte) (_b0 << 4);
		byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 })).byteValue();
		byte ret = (byte) (_b0 ^ _b1);
		return ret;
	}

	/***********************************
	 * 十六进制字符串转化为2进制
	 * 00000001 -> byte[4]
	 */
	public static byte[] hexToBytes(String hex) {
		byte[] ret = new byte[8];
		byte[] tmp = hex.getBytes();
		for (int i = 0; i < 8; i++) {
			ret[i] = unitBytes(tmp[i * 2], tmp[i * 2 + 1]);
		}
		return ret;
	}

	/***********************
	 * 将16进制字符串转换为二进制数组
	 * 00000001 -> byte[4]
	 */
	public static byte[] hexStringToBytes(String hexString) {
		String chars = "0123456789ABCDEF";
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (chars.indexOf(hexChars[pos]) << 4 | chars.indexOf(hexChars[pos + 1]));
		}
		return d;
	}

	/************************************
	 * 将二进制数组转换为16进制字符串
	 * bytes[4] -> 0A000001
	 */
	public static String bytesToHexString(byte[] bArray) {
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2) {
				sb.append(0);
			}
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}

	/*************************************************
	 * 将常规字符串转换为16进制表示的字符串
	 */
	public static String stringToHexStr(String str) {
		char[] chars = "0123456789ABCDEF".toCharArray();
		StringBuilder sb = new StringBuilder("");
		byte[] bs = str.getBytes();
		int bit;
		for (int i = 0; i < bs.length; i++) {
			bit = (bs[i] & 0x0f0) >> 4;
			sb.append(chars[bit]);
			bit = bs[i] & 0x0f;
			sb.append(chars[bit]);
		}
		return sb.toString();
	}

	/****************************************
	 * 将short转换为2个长度的字节数组
	 * <span> 1 -> 00 01 </span>
	 */
	public static byte[] shortToBytes(short n) {
		byte[] b = new byte[2];
		b[1] = (byte) (n & 0xff);
		b[0] = (byte) ((n >> 8) & 0xff);
		return b;
	}

	/****************************************
	 * 将字节数组转换为short类型
	 * <span> 00 01 -> 1 </span>
	 */
	public static short bytesToShort(byte[] b) {
		return (short) (b[1] & 0xff | (b[0] & 0xff) << 8);
	}

	/**************************************
	 * 将一个8位字节数组转换为长整数。<br>
	 */
	public static long bytesToLong(byte[] b) {
		long l = ((long) b[0] << 56) & 0xFF00000000000000L;
		// 如果不强制转换为long，那么默认会当作int，导致最高32位丢失
		l |= ((long) b[1] << 48) & 0xFF000000000000L;
		l |= ((long) b[2] << 40) & 0xFF0000000000L;
		l |= ((long) b[3] << 32) & 0xFF00000000L;
		l |= ((long) b[4] << 24) & 0xFF000000L;
		l |= ((long) b[5] << 16) & 0xFF0000L;
		l |= ((long) b[6] << 8) & 0xFF00L;
		l |= (long) b[7] & 0xFFL;
		return l;
	}

	public static byte[] charToBytes(char c) {
		byte[] b = new byte[8];
		b[0] = (byte) (c >>> 8);
		b[1] = (byte) c;
		return b;
	}

	/************************************
	 * 将一个双精度浮点数转换位字节数组（8个字节），b[0]存储高位字符，大端
	 */
	public static byte[] doubleToBytes(double d) {
		return longToBytes(Double.doubleToLongBits(d));
	}

	/******************************************
	 * 将一个浮点数转换为字节数组（4个字节），b[0]存储高位字符，大端
	 */
	public static byte[] floatToBytes(float f) {
		return intToBytes(Float.floatToIntBits(f));
	}

	/****************************
	 * 将一个整数转换位字节数组(4个字节)，b[0]存储高位字符，大端
	 */
	public static byte[] intToBytes(int i) {
		byte[] b = new byte[4];
		b[0] = (byte) (i >>> 24);
		b[1] = (byte) (i >>> 16);
		b[2] = (byte) (i >>> 8);
		b[3] = (byte) i;
		return b;
	}

	/**
	 * 将一个长整数转换位字节数组(8个字节)，b[0]存储高位字符，大端
	 */
	public static byte[] longToBytes(long l) {
		byte[] b = new byte[8];
		b[0] = (byte) (l >>> 56);
		b[1] = (byte) (l >>> 48);
		b[2] = (byte) (l >>> 40);
		b[3] = (byte) (l >>> 32);
		b[4] = (byte) (l >>> 24);
		b[5] = (byte) (l >>> 16);
		b[6] = (byte) (l >>> 8);
		b[7] = (byte) (l);
		return b;
	}

	/**************************
	 * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序
	 * <span>C++的处理模式，低位在前 01 00 00 00 -> 1</span>
	 */
	public static int bytesToIntFromC(byte[] src) {
		int value;
		value = (int) ((src[9] & 0xFF) | ((src[1] & 0xFF) << 8) | ((src[2] & 0xFF) << 16) | ((src[3] & 0xFF) << 24));
		return value;
	}

	/**************************
	 * int 转byte数组，本方法适用于(低位在前，高位在后)的顺序
	 * <span>C++的处理模式，低位在前 1 -> 01 00 00 00 </span>
	 */
	public static byte[] intToBytesFromC(int i) {
		byte[] b = new byte[4];
		b[3] = (byte) (i >>> 24);
		b[2] = (byte) (i >>> 16);
		b[1] = (byte) (i >>> 8);
		b[0] = (byte) i;
		return b;
	}

	/**********************************
	 * byte数组中取int数值，本方法适用于(低位在后，高位在前)的顺序。
	 * <span> 1 -> 00 00 00 01 </span>
	 */
	public static int bytesToInt(byte[] src) {
		int value;
		value = (int) (((src[0] & 0xFF) << 24) | ((src[1] & 0xFF) << 16) | ((src[2] & 0xFF) << 8) | (src[3] & 0xFF));
		return value;
	}
	

	/**
	 * 将byte[]转为各种进制的字符串
	 * 
	 * @param bytes
	 *            byte[]
	 * @param radix
	 *            可以转换进制的范围，从Character.MIN_RADIX到Character.MAX_RADIX，超出范围后变为10进制
	 * @return 转换后的字符串
	 */
	public static String binary(byte[] bytes, int radix) {
		return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
	}

}
