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
把上面的代码复制进去就可以了,这个在线的便宜工具只能识别一些简单的类,像字节流那些还是不能识别的。

共勉:别忘了你是第一名

 

posted @ 2018-11-05 21:50  HappySimon  阅读(3761)  评论(0编辑  收藏  举报