Java基础数据类型二进制转换

前言:

本文主要介绍java基础类型的二进制转换和二进制的基本概念。

二进制:

1,二进制是以0和1为码,逢2进1,比如3=11=1*2+1。

2,在计算机当中其它进制的算法基本基于2进制,因为计算机只认识0和1,比如16进制数则意味着一位16进制码由4位2进制码数表示。

3,在Java语言中byte代表最小计量单位,byte由8位2进制数组成。

Java基本数据类型与表示范围(boolean忽略)

1,byte(整型):8位,short(整型):16位,char(字符型):16位,int(整型):32位,float(浮点型单精度):32位,long(整型):64位,double(浮点型双精度):64位。

2,直接按位做比例运算,一个short数字或char字符可有两个byte数字表示,一个float或int数字可由4个byte数字表示,一个long或double数字可由8个byte数字表示。

3,以2进制数表示范围计算得到各整型数值表示范围,每种数值类型的最大表示范围可以通过包装类的静态属性取到,比如Integer.MAX_VALUE。

4,char类型是最具话题性的数据类型,它承担着整个语言世界的符号统统转换称为计算机所认识的编码格式的重任,关于字符集和编码包含了很多概念也带来了很多问题,比如通行的utf-8编码格式。

二进制与编码

一般对英文字符而言,一个字节表示一个字符,但是对汉字而言,由于低位的编码已经被使用(早期计算机并不支持中文,因此为了扩展支持,唯一的办法就是采用更多的字节数)只好向高位扩展。

一般字符集编码的范围 utf-8>gbk>iso-8859-1(latin1)>ascll。ascll编码是美国标准信息交换码的英文缩写,包含了常用的字符,如阿拉伯数字,英文字母和一些打印符号,请注意字符和数字的区别,比如‘0‘字符对应的十进制数字是48。

unicode编码包含很多种格式,utf-8是其中最常用的一种,utf-8名称的来自于该编码使用8位一个字节表示一个字符。对于一个汉字而言,它需要3个字节表示一个汉字,但大中华地区人民表示不服,搞一套gbk编码格式,用两个字节表示一个汉字。

乱码问题:

乱码问题的根源在于信息解码和编码时使用的格式不统一,参考IBM社区的一篇文章《深入分析Java中文编码问题》。

示例1--简单&运算示例

    @Test
    public void demo(){
        // 0100&0100=0100
        assertEquals(4,4&4);
        // 1000&0100=0000
        assertEquals(0,4&8);

        // 字符‘0‘用十进制数48表示
        char c = ‘0‘;
        int i = c;
        assertEquals(48,i);

        // 认识 0xf, 0xff, 0xffff. f对应16进制数字15, 二进制1111
        byte b = Byte.MAX_VALUE;
        assertEquals(127,b);
        assertEquals(127,b & 0xff);
        assertEquals(15,b & 0xf);

        byte b1 =  -1;
        // 说明-1是按照默认的(byte)b1=0xff与0xff计算后转换为int值 = 255
        assertEquals(255, (byte)b1&0xff);
        assertEquals(255, b1&0xff);
        // 255转换为byte 结果为-1
        assertEquals(-1, (byte)(b1&0xff));
        // b1不强制转换编译器会报错. 0xff超过byte表示范围转为byte值得到-1
        byte bf = (byte) 0xff;
        assertEquals(bf, -1);
        // 0xf2 = 11110010
        // 符号位不变取反+1 = 10001101+00000001 = 10001110 = -14
        assertEquals(-14, (byte)0xf2);
    }

上面的代码包含了几个基本的运算和转换的示例。

二进制与其它类型直接的转换

工具类ByteUtils.java

package org.wit.ff.common;

/**
 *
 * <pre>
 * 基本数据类型转换(主要是byte和其它类型之间的互转).
 * </pre>
 *
 * @author F.Fang
 * @version $Id: ByteUtils.java, v 0.1 2014年11月9日 下午11:23:21 F.Fang Exp $
 */
public class ByteUtils {

    /**
     *
     * <pre>
     * 将4个byte数字组成的数组合并为一个float数.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static float byte4ToFloat(byte[] arr) {
        if (arr == null || arr.length != 4) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是4位!");
        }
        int i = byte4ToInt(arr);
        return Float.intBitsToFloat(i);
    }

    /**
     *
     * <pre>
     * 将一个float数字转换为4个byte数字组成的数组.
     * </pre>
     *
     * @param f
     * @return
     */
    public static byte[] floatToByte4(float f) {
        int i = Float.floatToIntBits(f);
        return intToByte4(i);
    }

    /**
     *
     * <pre>
     * 将八个byte数字组成的数组转换为一个double数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static double byte8ToDouble(byte[] arr) {
        if (arr == null || arr.length != 8) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是8位!");
        }
        long l = byte8ToLong(arr);
        return Double.longBitsToDouble(l);
    }

    /**
     *
     * <pre>
     * 将一个double数字转换为8个byte数字组成的数组.
     * </pre>
     *
     * @param i
     * @return
     */
    public static byte[] doubleToByte8(double i) {
        long j = Double.doubleToLongBits(i);
        return longToByte8(j);
    }

    /**
     *
     * <pre>
     * 将一个char字符转换为两个byte数字转换为的数组.
     * </pre>
     *
     * @param c
     * @return
     */
    public static byte[] charToByte2(char c) {
        byte[] arr = new byte[2];
        arr[0] = (byte) (c >> 8);
        arr[1] = (byte) (c & 0xff);
        return arr;
    }

    /**
     *
     * <pre>
     * 将2个byte数字组成的数组转换为一个char字符.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static char byte2ToChar(byte[] arr) {
        if (arr == null || arr.length != 2) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是2位!");
        }
        return (char) (((char) (arr[0] << 8)) | ((char) arr[1]));
    }

    /**
     *
     * <pre>
     * 将一个16位的short转换为长度为2的8位byte数组.
     * </pre>
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte2(Short s) {
        byte[] arr = new byte[2];
        arr[0] = (byte) (s >> 8);
        arr[1] = (byte) (s & 0xff);
        return arr;
    }

    /**
     *
     * <pre>
     * 长度为2的8位byte数组转换为一个16位short数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static short byte2ToShort(byte[] arr) {
        if (arr != null && arr.length != 2) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是2位!");
        }
        return (short) (((short) arr[0] << 8) | ((short) arr[1] & 0xff));
    }

    /**
     *
     * <pre>
     * 将short转换为长度为16的byte数组.
     * 实际上每个8位byte只存储了一个0或1的数字
     * 比较浪费.
     * </pre>
     *
     * @param s
     * @return
     */
    public static byte[] shortToByte16(short s) {
        byte[] arr = new byte[16];
        for (int i = 15; i >= 0; i--) {
            arr[i] = (byte) (s & 1);
            s >>= 1;
        }
        return arr;
    }

    public static short byte16ToShort(byte[] arr) {
        if (arr == null || arr.length != 16) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度为16!");
        }
        short sum = 0;
        for (int i = 0; i < 16; ++i) {
            sum |= (arr[i] << (15 - i));
        }
        return sum;
    }

    /**
     *
     * <pre>
     * 将32位int转换为由四个8位byte数字.
     * </pre>
     *
     * @param sum
     * @return
     */
    public static byte[] intToByte4(int sum) {
        byte[] arr = new byte[4];
        arr[0] = (byte) (sum >> 24);
        arr[1] = (byte) (sum >> 16);
        arr[2] = (byte) (sum >> 8);
        arr[3] = (byte) (sum & 0xff);
        return arr;
    }

    /**
     * <pre>
     * 将长度为4的8位byte数组转换为32位int.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static int byte4ToInt(byte[] arr) {
        if (arr == null || arr.length != 4) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是4位!");
        }
        return (int) (((arr[0] & 0xff) << 24) | ((arr[1] & 0xff) << 16) | ((arr[2] & 0xff) << 8) | ((arr[3] & 0xff)));
    }

    /**
     *
     * <pre>
     * 将长度为8的8位byte数组转换为64位long.
     * </pre>
     *
     * 0xff对应16进制,f代表1111,0xff刚好是8位 byte[]
     * arr,byte[i]&0xff刚好满足一位byte计算,不会导致数据丢失. 如果是int计算. int[] arr,arr[i]&0xffff
     *
     * @param arr
     * @return
     */
    public static long byte8ToLong(byte[] arr) {
        if (arr == null || arr.length != 8) {
            throw new IllegalArgumentException("byte数组必须不为空,并且是8位!");
        }
        return (long) (((long) (arr[0] & 0xff) << 56) | ((long) (arr[1] & 0xff) << 48) | ((long) (arr[2] & 0xff) << 40)
                        | ((long) (arr[3] & 0xff) << 32) | ((long) (arr[4] & 0xff) << 24)
                        | ((long) (arr[5] & 0xff) << 16) | ((long) (arr[6] & 0xff) << 8) | ((long) (arr[7] & 0xff)));
    }

    /**
     * 将一个long数字转换为8个byte数组组成的数组.
     */
    public static byte[] longToByte8(long sum) {
        byte[] arr = new byte[8];
        arr[0] = (byte) (sum >> 56);
        arr[1] = (byte) (sum >> 48);
        arr[2] = (byte) (sum >> 40);
        arr[3] = (byte) (sum >> 32);
        arr[4] = (byte) (sum >> 24);
        arr[5] = (byte) (sum >> 16);
        arr[6] = (byte) (sum >> 8);
        arr[7] = (byte) (sum & 0xff);
        return arr;
    }

    /**
     *
     * <pre>
     * 将int转换为32位byte.
     * 实际上每个8位byte只存储了一个0或1的数字
     * 比较浪费.
     * </pre>
     *
     * @param num
     * @return
     */
    public static byte[] intToByte32(int num) {
        byte[] arr = new byte[32];
        for (int i = 31; i >= 0; i--) {
            // &1 也可以改为num&0x01,表示取最地位数字.
            arr[i] = (byte) (num & 1);
            // 右移一位.
            num >>= 1;
        }
        return arr;
    }

    /**
     *
     * <pre>
     * 将长度为32的byte数组转换为一个int类型值.
     * 每一个8位byte都只存储了0或1的数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static int byte32ToInt(byte[] arr) {
        if (arr == null || arr.length != 32) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度是32!");
        }
        int sum = 0;
        for (int i = 0; i < 32; ++i) {
            sum |= (arr[i] << (31 - i));
        }
        return sum;
    }

    /**
     *
     * <pre>
     * 将长度为64的byte数组转换为一个long类型值.
     * 每一个8位byte都只存储了0或1的数字.
     * </pre>
     *
     * @param arr
     * @return
     */
    public static long byte64ToLong(byte[] arr) {
        if (arr == null || arr.length != 64) {
            throw new IllegalArgumentException("byte数组必须不为空,并且长度是64!");
        }
        long sum = 0L;
        for (int i = 0; i < 64; ++i) {
            sum |= ((long) arr[i] << (63 - i));
        }
        return sum;
    }

    /**
     *
     * <pre>
     * 将一个long值转换为长度为64的8位byte数组.
     * 每一个8位byte都只存储了0或1的数字.
     * </pre>
     *
     * @param sum
     * @return
     */
    public static byte[] longToByte64(long sum) {
        byte[] arr = new byte[64];
        for (int i = 63; i >= 0; i--) {
            arr[i] = (byte) (sum & 1);
            sum >>= 1;
        }
        return arr;
    }

}

测试用例:

1,测试基本的移位操作符号.

    @Test
    public void op(){
        // >>>
        // >>
        // <<<
        int i = -1;
        System.out.println(Arrays.toString(ByteUtils.intToByte32(i)));

        // 有符号右移,符号位依然存在,右移一位后最左边的最高位补1, -1
        System.out.println(i >> 1);

        // 无符号右移,忽略符号位,右移一位后最左边的最高位补0,2147483647 Integer.MAX_VALUE
        System.out.println(i >>> 1);

        // 有符号左移,符号位依然存在,左移一位最低位补0. -2
        System.out.println(i << 1);
        // <<<无此符号,因为左移符号位不会丢失,没有必要再增加此操作.
    }

2,查询最大值最小值.

    @Test
    public void showMaxValAndminVal() {
        // 127
        System.out.println(Byte.MAX_VALUE);
        // -128
        System.out.println(Byte.MIN_VALUE);

        // 32767
        System.out.println(Short.MAX_VALUE);
        // -32768
        System.out.println(Short.MIN_VALUE);

        // 65535 2的16次方-1
        System.out.println((int) Character.MAX_VALUE);
        // 0
        System.out.println((int) Character.MIN_VALUE);

        // 2147483647
        System.out.println(Integer.MAX_VALUE);
        // -2147483648
        System.out.println(Integer.MIN_VALUE);

        // 科学计数法.
        // 3.4028235E38
        System.out.println(Float.MAX_VALUE);
        // 1.4E-45
        System.out.println(Float.MIN_VALUE);

        // 9223372036854775807
        System.out.println(Long.MAX_VALUE);
        // -9223372036854775808
        System.out.println(Long.MIN_VALUE);

        // 科学计数法.
        // 1.7976931348623157E308
        System.out.println(Double.MAX_VALUE);
        // 4.9E-324
        System.out.println(Double.MIN_VALUE);
    }

3,转换测试:

    @Test
    public void transByte() {
        char c = ‘z‘;
        byte[] charToByte2Arr = ByteUtils.charToByte2(c);
        assertEquals("[0, 122]", Arrays.toString(charToByte2Arr));
        assertEquals(‘z‘, ByteUtils.byte2ToChar(charToByte2Arr));

        short s = Short.MAX_VALUE;
        // System.out.println("Short.MAX_VALUE:" + s);
        byte[] shortToByte2Arr = ByteUtils.shortToByte2(s);
        assertEquals("[127, -1]", Arrays.toString(shortToByte2Arr));
        assertEquals(s, ByteUtils.byte2ToShort(shortToByte2Arr));

        byte[] shortToByte16 = ByteUtils.shortToByte16(s);
        System.out.println(Arrays.toString(shortToByte16));
        System.out.println(ByteUtils.byte16ToShort(shortToByte16));

        int i = Integer.MAX_VALUE;
        // System.out.println("Integer.MAX_VALUE:" + i);
        byte[] intToByte4Arr = ByteUtils.intToByte4(i);
        assertEquals("[127, -1, -1, -1]", Arrays.toString(intToByte4Arr));
        assertEquals(i, ByteUtils.byte4ToInt(intToByte4Arr));

        byte[] intToByte32Arr = ByteUtils.intToByte32(i);
        System.out.println(Arrays.toString(intToByte32Arr));
        System.out.println(ByteUtils.byte32ToInt(intToByte32Arr));

        long j = Long.MAX_VALUE;
        // System.out.println("Long.MAX_VALUE:" + j);
        byte[] longToByte8Arr = ByteUtils.longToByte8(j);
        assertEquals("[127, -1, -1, -1, -1, -1, -1, -1]", Arrays.toString(longToByte8Arr));
        assertEquals(j, ByteUtils.byte8ToLong(longToByte8Arr));

        byte[] longToByte64Arr = ByteUtils.longToByte64(j);
        System.out.println(Arrays.toString(longToByte64Arr));
        System.out.println(ByteUtils.byte64ToLong(longToByte64Arr));

        double d = 2.34;
        byte[] doubleToByte8Arr = ByteUtils.doubleToByte8(d);
        assertEquals("[64, 2, -72, 81, -21, -123, 30, -72]", Arrays.toString(doubleToByte8Arr));
        // double类型不能直接做等值比较,只能在精度范围做差值比较.
        assertEquals(d + "", ByteUtils.byte8ToDouble(doubleToByte8Arr) + "");

        float f = 1.2f;
        byte[] floatToByte4Arr = ByteUtils.floatToByte4(f);
        assertEquals("[63, -103, -103, -102]", Arrays.toString(floatToByte4Arr));
        assertEquals(f + "", ByteUtils.byte4ToFloat(floatToByte4Arr) + "");
    }
时间: 2024-10-07 06:08:36

Java基础数据类型二进制转换的相关文章

Java基础-进制转换

Java基础-进制转换 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Java 程序中常用的进制 1>.十进制,由"0123456789" 这10个数字组成,逢十进一: 2>.二进制,由"01" 这2个数字组成,逢二进一,以"0b"开头: 3>.八进制,由"01234567" 这8个数字组成,逢八进一,以数字"0"开头: 4>.十六进制,由"0123

JAVA基本数据类型及其转换

Java语言是一种强类型语言.这意味着每个变量都必须有一个声明好的类型.Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型.Java另外还提供大数字对象,但它不是Java的数据类型. 1.整数: 定义:没有小数部分的数字,负数是允许的. 种类:Java提供四种整数类型: byte 1个字节(8bit) -128到127(-27~27-1)  默认为0 ,如 byte b=28; short 2个字节(16bit) -32,768到32,767(-

Java基础——数据类型之间的转换

Java数据类型分为三大类,即布尔型.字符型和数值型.其中数值型又分为整型和浮点型.Java的基本数据类型(8种)为布尔型boolean(1字节):字符型char(2字节):整型byte(1字节).short(2字节).int(4字节).long(8字节):浮点型float(4字节).double(8字节).此外,编程时还经常用到两种类变量,String和Date. Java数据类型的转换一般分三种,分别是:简单数据类型之间的转换.字符串与其他数据类型的转换.其他实用数据类型的转换. 简单数据类

java的数据类型的转换

一:java的数据类型转换除布尔类型boolean(不能转换)有两种:<一> 自动转换: <二> 强制转换 <一>.自动转换:就是将小的数据类型自动转换成大的数据类型.如:int与byte计算时,byte(-128~127)自动的转换成int(-2147483648~2147483647)的类型. 0.1.基本数据类型自动转换: byte->short,char -> int -> long float -> double int -> f

Java中数据类型的转换

Java中的数据类型在定义时其实就已经确定了,所以是不能随意转换成其它的数据类型的.我们只能在一定程度上对其做类型转换的处理.转换的方式有 “自动类型转换”和“强制类型转换”两种. ①数据类型的自动转换: 假若在程序中定义好数据类型变量以后,又想用另一种数据类型来表示.Java只有在下列的条件都满足的情况下,才会做出数据类型的转换: 1.转换前的数据类型与转换后的类型兼容,也就是说只能是同一种数据类型,要么都是数值型,要么都是字符类型的: 2.转换后的数据类型表示范围比转换前的类型表示的范围大.

Java基础——隐式转换vs强制转换

在定义变量时,有许多要注意的问题,一不小心就会出现损失精度或者不兼容类型等问题. 例如: 1.定义长整型数据时,必须加后缀l或L long l =123456789012345L 2.定义单精度类型时(7-8位有效数字),必须加后缀 f 或 F float f = 12.5F 3. boolean类型不可以转换为其它的数据类型. 这其中,我们常常会遇到数据类型的转换问题,最为常见的要属隐式转换和强制转换了,我们来分析一下. 隐式转换 特征: 从小到大,可以隐式转换,数据类型将自动提升. byte

java基础数据类型char

java基础类型 数据类型            大小       范围                                             默认值  byte(字节)      8         -128 - 127                                           0 shot(短整型)        16      -32768 - 32768                                         0 int

好记性不如烂笔头1-JAVA基础数据类型和转换

一.基础数据类型 1.布尔型(boolean) 布尔型(boolean) :true/false,不可以以0或非0的数字代替:不能进行数据之间的转换. 2.整数类型 整型默认为int型,而long类型表示的范围要超出int表数范围,所以,声明long类型时,常量后要加L(l). 如:long l1=12345678 //  数值在int范围之内,还不会出错 longl2=8888888888;//  数值在int范围之外,会出错 longl3=8888888888L; //正确 3.浮点类型 浮

Java 基础数据类型包装类的高频区间的数据缓存

一.Java的基础数据类型的包装类:Integer,Long,Double,Float,Boolean,Byte,Short,Character. 二.高频缓存区 其中Double和Float没有缓存,其他类型都有高频缓存区间.其高频缓存区间的缓存范围是:Boolean:使用静态final,就会返回静态值Byte:-128~127Short:-128~127Character:0~127Long:-128~127Integer:-128~127 如果所使用的包装类的值在这个缓存区间内,就会直接复