Java byte数据转换和处理总结
一.byte和int相互转换的方法
java程序或Android程序的socket数据传输,都是通过byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型。
/** * int到byte[] * @param i * @return */ public static byte[] intToByteArray(int i) { byte[] result = new byte[4]; // 由高位到低位 result[0] = (byte) ((i >> 24) & 0xFF); result[1] = (byte) ((i >> 16) & 0xFF); result[2] = (byte) ((i >> 8) & 0xFF); result[3] = (byte) (i & 0xFF); return result; } /** * byte[]转int * @param bytes * @return */ public static int byteArrayToInt(byte[] bytes) { int value = 0; // 由高位到低位 for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (bytes[i] & 0x000000FF) << shift;// 往高位游 } return value; } //测试数据 public static void main(String[] args) { byte[] b = intToByteArray(128); System.out.println(Arrays.toString(b));//打印byte的每一个字节 int i = byteArrayToInt(b); System.out.println(i); //打印byte转变为Int后的数据 }
二.byte和String相互转换
上面只说到byte和int的相互转换,其实呢byte和String也是可以相互转换的,毕竟Socket通信也是需要传递字符串的。
其他的方面,char和long、float这些数据都是可以转换为byte的,但是实际应用场合比较少。
//String 和byte相互转换的示例 String string = "hello 世界小姐"; byte[] bytes = string.getBytes();//获得byte数组 System.out.println("bytes-->" + Arrays.toString(bytes));//打印byte数组 System.out.println("string-->" + new String(bytes));//获得byte数组转换来的String数据,并打印
上面第一第二都是byte数组和其他数据相互转换,其实也可以通过流的来获取字节,传递过去后再把字节放到流里面去,解封出来,但是那样还是太麻烦的!不建议做。
三.byte占用字节大小详解
在Java中一共有8种基本数据类型,其中有4种整型,2种浮点类型,1种用于表示Unicode编码的字符单元的字符类型和1种用于表示真值的boolean类型。(一个字节等于8个bit)
1.整型
类型 存储需求 bit 取值范围 备注
int 4字节 4*8 很大
short 2字节 2*8 -32768~32767
long 8字节 8*8 非常大
byte 1字节 1*8 -128~127
2.浮点型
类型 存储需求 bit 取值范围 备注
float 4字节 4*8 很大 float类型的数值有一个后缀F(例如:3.14F)
double 8字节 8*8 非常大 没有后缀F的浮点数值(如3.14)默认为double类型
3.char类型
类型 存储需求 bit 取值范围 备注
char 2字节 2*8 -32768~32767
4.boolean类型
类型 存储需求 bit 取值范围 备注
boolean 1字节 1*8 false、true
四.String与byte[]字节数组中文转换乱码问题
在Java中,String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示,如
byte[] b_gbk = “中”.getBytes(“GBK”);
byte[] b_utf8 = “中”.getBytes(“UTF-8”);
byte[] b_iso88591 = “中”.getBytes(“ISO8859-1”);
byte[] b_unicode = “中”.getBytes(“unicode”);
将分别返回“中”这个汉字在GBK、UTF-8和ISO8859-1编码下的byte数组表示,
此时b_gbk的长度为2,b_utf8的长度为3,b_iso88591的长度为1,
b_unicode 的长度为4(系统的的unicode采用的是big-endian就是前面是两个字节来表示这个的,unicode采用的都是两个字节编码,所以后面是4个字节 )。
而与getBytes相对的,可以通过new String(byte[], decode)的方式来还原这个“中”字时,这个new String(byte[], decode)实际是使用decode指定的编码来将byte[]解析成字符串。
String s_gbk = new String(b_gbk,”GBK”);
String s_utf8 = new String(b_utf8,”UTF-8”);
String s_iso88591 = new String(b_iso88591,”ISO8859-1”);
通过打印s_gbk、s_utf8和s_iso88591,会发现,s_gbk和s_utf8都是“中”,而只有s_iso88591是一个不认识的字符,为什么使用ISO8859-1编码再组合之后,
无法还原“中”字呢,其实原因很简单,因为ISO8859-1编码的编码表中,
根本就没有包含汉字字符,当然也就无法通过”中”.getBytes(“ISO8859-1”);来得到正确的“中”字在ISO8859-1中的编码值了,所以再通过new String()来还原就无从谈起了。
因此,通过String.getBytes(String decode)方法来得到byte[]时,一定要确定decode的编码表中确实存在String表示的码值,这样得到的byte[]数组才能正确被还原。
有时候,为了让中文字符适应某些特殊要求(如http header头要求其内容必须为iso8859-1 编码),可能会通过将中文字符按照字节方式来编码的情况,
如 String s_iso88591 = new String(“中”.getBytes(“UTF-8”),”ISO8859-1”),这样得到的s_iso8859-1字符串实际是三个在ISO8859-1中的字符,
在将这些字符传递到目的地后,目的地程序再通过相反的方式String s_utf8 = new String(s_iso88591.getBytes(“ISO8859-1”),”UTF-8”)来得到正确的中文汉字“中”。
这样就既保证了遵守协议规定、也支持中文。
String的getBytes()方法是得到一个字串的字节数组,这是众所周知的。但特别要注意的是,本方法将返回该操作系统默认的编码格式的字节数组。
如果你在使用这个方法时不考虑到这一点,你会发现在一个平台上运行. 良好的系统,放到另外一台机器后会产生意想不到的问题。
对也String来说,一个英文字符固定占1个字节,而中文字符占2个(GBK编码)或3个(UTF-8编码)字节。
五.byte字节其他的知识
两个字节能不能表示一个int呢?
其实也是可以的,就是有一些坑会在里面!
代码:
int a = 100; byte b1 = (byte) ((a >> 8) & 0xFF); //高8位 byte b2 = (byte) (a & 0xFF); //低8位 System.out.println(a+"-->"+(b1)+(b2) ); int value = 0; value += (b1 & 0xFF) << 8;// 往高位游 value += (b2 & 0xFF);// System.out.println("value=" + value);
如果a的数值在0到32767之内都是正常的。
正常情况是没有问题的,像一般字符串的长度用两个字节的byte和int相互转换来表示长度,但是如果是负数就不可以用两个字节byte来和int相互转换了。
因为如果是负数的话符号位就是1了,左移和右移有很大想差别。
像会出现负数的情况还是要使用四个byte来和int做相互转换传递数据。
在线测试一下
如果想简单验证也可以使用在线java编译工具,测试一下:
http://www.runoob.com/try/runcode.php?filename=HelloWorld&type=java
把上面的代码复制进去就可以了,这个在线的便宜工具只能识别一些简单的类,像字节流那些还是不能识别的。
共勉:别忘了你是第一名