基本类型转换为字节流
字节流转换回基本类型
注意理解:
0xff &0xff java移位仅支持int或long
>>带符号右移(负数高位补1,正数高位补0),相当于除以2的n次方
>>>无符号右移(高位补0)
<<左移(低位补0),相当于乘以2的次方
/**
* ASCII码 0x00~0x7F
* ISO8859-1/Latin-1西欧标码
* gb2312中文简体 16进制范围0xB0A1~0xF7FE unicode表示范围\u4E00~\u9FA5 \uF900~\uFA2D
* GBK扩充的gb2312 16进制范围0x8140~0xFEFE
* 表示汉字的首1位bit都为1,而ASCII首1位bit为0,所以GBK编码时,判断是否汉字if(bytex<0)
* UTF-16LE小头(低位为0) 中文/英文字符都是占据两个字节 也叫Unicode编码 (JVM就是处理Unicode值的) 举例:'a' 0x6100
* UTF-16BE大头(高位为0) 中文/英文字符都是占据两个字节 也叫Unicode编码 (JVM就是处理Unicode值的) 举例:'a' 0x0061
* UTF-8编码 高8位是111打头的表示随后的三个字节凑在一起才是一个字符 例如中文
* 高8位是110打头的表示随后的两个字节凑在一起才是一个字符 例如脱离ISO8859-1范围的字符
* 高8位的首位是0的表示单字节的字符 例如ASCII范围内的字符
* UTF-32编码 每个字符都是硬性规定占4个字节
*/
/**
* ASCII码 0x00~0x7F
* ISO8859-1/Latin-1西欧标码
* gb2312中文简体 16进制范围0xB0A1~0xF7FE(其中有5个空位是D7FA-D7FE) unicode表示范围\u4E00~\u9FA5 \uF900~\uFA2D
* GBK扩充的gb2312 16进制范围0x8140~0xFEFE
* 由于表示汉字或图形符号的“高位字节”的首个bit都为1,而ASCII首个bit为0,而实现了这两种字符集对ASCII的兼容
* UTF-16LE小头(低位为0) 中文/英文字符都是占据两个字节 也叫Unicode编码 (Java内部机制就是处理Unicode值的) 举例:'a' 0x6100
* UTF-16BE大头(高位为0) 中文/英文字符都是占据两个字节 也叫Unicode编码 (Java内部机制就是处理Unicode值的) 举例:'a' 0x0061
* UTF-8编码 高8位是111打头的表示随后的三个字节凑在一起才是一个字符 例如中文
* 高8位是110打头的表示随后的两个字节凑在一起才是一个字符 例如脱离ISO8859-1范围的字符
* 高8位的首位是0的表示单字节的字符 例如ASCII范围内的字符
* UTF-32编码 每个字符都是硬性规定占4个字节
*/
/**
* Java基本数据类型和byte数组相互转化的工具类
*
* 0xff 16进制表示法(每一个数字代表4bit) 32位在计算机内表示为 00000000 00000000 00000000 11111111 等于十进制的255
*
* << 左移运算符:操作数向左移动N位(低位补0), 相当于操作数乘以2的几次方
* >> "有符号"右移运算符:操作数右移N位, 操作数为正时,高位补0 ; 操作数为正时,高位补1, 相当于操作数除以2的几次方
* >>> "无符号"右移运算符:操作数右移N位(高位补0)
*
* 对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int(因为java的移位操作仅支持int位移 或者 long位移)
*
* 所以由此延申出的 byte的字节移位时,为什么要&0xff呢?其作用就是仅关心当前8bit这一字节,其它bit位都置为零,保持二进制补码的一致性;
*
* 举例:* 最高 高 稍高 最低
255 0xff 00000000 00000000 00000000 11111111
-1 (byte)0xff 11111111 11111111 11111111 11111111
1 0xff>>>7 00000000 00000000 00000000 00000001 >>>1111111
33554431 ((byte)0xff)>>>7 00000000 00000001 11111111 11111111 >>>1111111
*
* &0xff 的作用:举例 int i = (byte)( -129 & 0xff );
* -129 32位bit补码表示:原码:00000000 00000000 00000000 10000001
* 求反:11111111 11111111 11111111 01111110
* 加1:11111111 11111111 11111111 01111111
* 0xff 默认为int类型: 00000000 00000000 00000000 11111111
* -129 & 0xff 的值为: 00000000 00000000 00000000 01111111
* (byte)(-129&0xff)关心最低8位时:01111111
* (byte)((-129>>8)&0xff)关心稍高8位时:11111111
* 我们想把-129变成byte数组存储时,数组里面就是[11111111],[011111111]
* 我们想把byte数组存储的转换为数值-129时,手法就是 short k = (byte[0]&0xff)<<8 | byte[1]&0xff 注意:移位操作java中仅支持int位移或long位移
*
* short k = (byte[0]&0xff)<<8 | byte[1]&0xff 的运算步骤
*
* byte[0]&0xff 运算:
* 第一步:byte[0]装入内存,高位补1, 机器内存中表示为:11111111 11111111 11111111 11111111
* 0xff装入内存,机器内存中表示为: 00000000 00000000 00000000 11111111
* byte[0]&0xff的结果: 00000000 00000000 00000000 11111111
*
* 第二步:(byte[0]&0xff)<<8的结果: 00000000<< 00000000 00000000 11111111 00000000 最高位左移走,低位补0
* 第三步:byte[1]装入内存,高位补0, 机器内存中表示为:00000000 00000000 00000000 01111111
* 0xff装入内存,机器内存中表示为: 00000000 00000000 00000000 11111111
* byte[1]&0xff的结果: 00000000 00000000 00000000 01111111
*
* 第四步:(byte[0]&0xff)<<8 | byte[1]&0xff 的运算:00000000 00000000 11111111 00000000
* |
* 00000000 00000000 00000000 01111111
*
* 结果为:00000000 00000000 11111111 01111111
*
* 第五步:结果类型强转(int->short,丢弃最高,高):short k = -129; //也就是仅用稍高字节,最低字节 11111111 01111111
*/
public class ByteUtil {
/**
* 得到基本类型的字节流
* 泛型静态方法 public static <T> T xxMethod(T t){}
*/
public static <T> byte[] getBytes(T t){
byte[] bytes = null ;
if( (t instanceof Short)){
short s = ((Short)t).shortValue();
bytes = new byte[2];
bytes[0] = (byte) (s);
bytes[1] = (byte) (s>>8);
}
else if(t instanceof Integer){
int i = ((Integer)t).intValue();
bytes = new byte[4];
bytes[0] = (byte) (i);
bytes[1] = (byte) (i>>8);
bytes[2] = (byte) (i>>2*8);
bytes[3] = (byte) (i>>3*8);
}
else if(t instanceof Long){
long l = ((Long)t).longValue();
bytes = new byte[8];
bytes[0] = (byte) (l);
bytes[1] = (byte) (l>>8);
bytes[2] = (byte) (l>>2*8);
bytes[3] = (byte) (l>>3*8);
bytes[4] = (byte) (l>>4*8);
bytes[5] = (byte) (l>>5*8);
bytes[6] = (byte) (l>>6*8);
bytes[7] = (byte) (l>>7*8);
}
else if(t instanceof Float){
int f = Float.floatToIntBits((Float)t);
bytes = new byte[4];
bytes[0] = (byte) (f);
bytes[1] = (byte) (f>>8);
bytes[2] = (byte) (f>>2*8);
bytes[3] = (byte) (f>>3*8);
}
else if(t instanceof Double){
long d = Double.doubleToLongBits((Double)t);
bytes = new byte[8];
bytes[0] = (byte) (d);
bytes[1] = (byte) (d>>8);
bytes[2] = (byte) (d>>2*8);
bytes[3] = (byte) (d>>3*8);
bytes[4] = (byte) (d>>4*8);
bytes[5] = (byte) (d>>5*8);
bytes[6] = (byte) (d>>6*8);
bytes[7] = (byte) (d>>7*8);
}
else if(t instanceof Character){
char c = ((Character)t).charValue();
bytes = new byte[2];
bytes[0] = (byte) (c);
bytes[1] = (byte) (c>>8);
}
return bytes;
}
/**
* 从字节流中获取基本类型的值
*/
public static <T> T getValue(byte[] bytes, Class<T> clazz ) {
T rtnObj = null;
if (clazz.equals(java.lang.Character.class)){
rtnObj = (T)Character.valueOf((char)((bytes[1]&0xff) << 8 | (bytes[0]&0xff)));
}
else if (clazz.equals(java.lang.Short.class)){
rtnObj = (T)(Short.valueOf((short)( (bytes[1]&0xff) << 8 | (bytes[0]&0xff) )));
}
else if (clazz.equals(java.lang.Integer.class)){
rtnObj = (T)(Object)( (bytes[3]&0xff) << 8*3
| (bytes[2]&0xff) << 8*2
| (bytes[1]&0xff) << 8
| (bytes[0]&0xff)
);
}
else if (clazz.equals(java.lang.Long.class)){
rtnObj = (T)(Object)( (bytes[7]&0xffL) << 8*7
| (bytes[6]&0xffL) << 8*6
| (bytes[5]&0xffL) << 8*5
| (bytes[4]&0xffL) << 8*4
| (bytes[3]&0xffL) << 8*3
| (bytes[2]&0xffL) << 8*2
| (bytes[1]&0xffL) << 8
| (bytes[0]&0xffL)
);
}
else if (clazz.equals(java.lang.Float.class)){
int intBit = ( (bytes[3]&0xff) << 8*3
| (bytes[2]&0xff) << 8*2
| (bytes[1]&0xff) << 8
| (bytes[0]&0xff)
);
rtnObj = (T)(Object)Float.intBitsToFloat(intBit);
}
else if (clazz.equals(java.lang.Double.class)){
long longBit = ( (bytes[7]&0xffL) << 8*7
| (bytes[6]&0xffL) << 8*6
| (bytes[5]&0xffL) << 8*5
| (bytes[4]&0xffL) << 8*4
| (bytes[3]&0xffL) << 8*3
| (bytes[2]&0xffL) << 8*2
| (bytes[1]&0xffL) << 8
| (bytes[0]&0xffL)
);
rtnObj = (T)(Object)Double.longBitsToDouble(longBit);
}
return rtnObj ;
}
public static void unicode(){
String str1 = "中文测试";
byte[] ch = new byte[100];
try {
ch = str1.getBytes("unicode");
System.out.println(str1+" length:"+ch.length+" unicode: "+byte2hex(ch));
ch = str1.getBytes("utf-16");
System.out.println(str1+" length:"+ch.length+" utf-16: "+byte2hex(ch));
//ch = str1.getBytes("UTF-16LE");
//System.out.println(str1+" length:"+ch.length+" UTF-16LE: "+byte2hex(ch));
//ch = str1.getBytes("UTF-16BE");
//System.out.println(str1+" length:"+ch.length+" UTF-16BE: "+byte2hex(ch));
ch = str1.getBytes("utf-8");
System.out.println(str1+" length:"+ch.length+" utf-8: "+byte2hex(ch));
ch = str1.getBytes("utf-32");
System.out.println(str1+" length:"+ch.length+" utf-32: "+byte2hex(ch));
str1 = "test";
ch = str1.getBytes("unicode");
System.out.println(str1+" length:"+ch.length+" unicode:"+byte2hex(ch));
ch = str1.getBytes("utf-8");
System.out.println(str1+" length:"+ch.length+" utf-8:"+byte2hex(ch));
ch = str1.getBytes("utf-16");
System.out.println(str1+" length:"+ch.length+" utf-16:"+byte2hex(ch));
ch = str1.getBytes("utf-32");
System.out.println(str1+" length:"+ch.length+" utf-32:"+byte2hex(ch));
/**
* 编码转换
*/
String str = "中国";
String iso88591 = new String(str.getBytes("UTF-8"), "ISO-8859-1"); //中文GBK --> UTF-8 --> ISO-8859-1
System.out.println(iso88591); //此时打印是6个问号,因为:一个中文UTF-8时是3个字节,两个中文就是6个字节,ISO又是单字节的字符
str = new String(iso88591.getBytes("ISO-8859-1"), "UTF-8"); //返向的 ISO-8859-1 --> UTF-8 --> 中文GBK
System.out.println(str);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String byte2hex( byte[] b) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
s.append( hex.toUpperCase() );
}
return s.toString() ;
}
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* Convert hex string to byte[]
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hexStringToBytes(String hexString) {
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) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
* @param c char
* @return byte
*/
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public static void main(String[] args) {
char c = 'A';
short s = -177 ;
int i = -12345678;
long l = -12345678900L;
float f = -1234.567F;
double d = -444444444.555555;
System.out.println( getValue(getBytes(c), Character.class) );
System.out.println( getValue(getBytes(s), Short.class) );
System.out.println( getValue(getBytes(i), Integer.class) );
System.out.println( getValue(getBytes(l), Long.class) );
System.out.println( getValue(getBytes(f), Float.class) );
System.out.printf("%f \r\n",getValue(getBytes(d),Double.class));
unicode();
}
}