基于JAVA实现modbus rtu通信(三)

本次我们主要探讨一下如何在java中实现数据的大小端转换问题,那么我们就需要知道数据传输有哪几种形式。

针对16位传输,只存在正序(AB)或反序(BA)两种方式。

针对双字32位数据传输,存在四种顺序方式:

Big-endian :ABCD
Little-endian :DCBA
Big-endian byte swap :BADC
Little-endian byte swap :CDAB

其实java中的包装类给我们提供了很方便的转换成字节数组的方法,那么我们开始实现字节顺序的转换把。

一、如何获取字节形式。

        要知道,在java中int和float都占4个字节,32位,因此我们可以只针对int类型进行处理,然后通过包装类型进行数据转换即可。借助下面方法即可把其他类型转为int或者long类型字节。

        

#float 转成int字节
float f = 17.61373519F;
int bigEndian = Float.floatToIntBits(f);
#double 转成long字节
double d = 123456.78964531;
long di = Double.doubleToLongBits(d);

 二、创建字节顺序转换工具类

        对于字节顺序操作效率最高的就是位运算了,这部分我们也可以在jdk源码中看到,jdk官方已经给我们提供了ABCD,DCBA两种顺序。

public class ByteOrderUtils{
    /**
     * Byte order is 'A B C D'
     * @param num int number
     * @return int number in big endian format
     */
    public static int BigEndian(int num){
        return num;
    }
    /**
     * Byte order is 'D C B A'
     * @param num int number
     * @return int number in little endian format
     */
    public static int LittleEndian(int num){
        return Integer.reverseBytes(num);
    }
    /**
     * Byte order is 'B A D C'
     * @param num int number
     * @return int number in big endian swap format
     */
    public static int BigEndianWordSwap(int num){
        return ((num&0xff00)>>>8)|
                ((num<<8)&0xff00)|
                ((num<<8)&0xff000000)|
                ((num &0xff000000)>>>8);
    }
    /**
     * Byte order is 'C D A B'
     * @param num int number
     * @return int number in little endian swap format
     */
    public static int LittleEndianWordSwap(int num){
        return (num << 16)|(num >>> 16);
    }



    /**
     * Byte order is 'A B C D E F G H'
     * @param num long number
     * @return long number in big endian format
     */
    public static long BigEndian(long num){
        return num;
    }

    /**
     * Byte order is 'H G F E D C B A'
     * @param num long number
     * @return long number in little endian format
     */
    public static long LittleEndian(long num){
        return Long.reverseBytes(num);
    }

    /**
     * Byte order is 'B A D C F E H G'
     * @param num long number
     * @return long number in big endian format
     */
    public static long BigEndianWordSwap(long num){

        return (num & 0x00ff00ff00ff00ffL) << 8 | (num >>> 8) & 0x00ff00ff00ff00ffL;
    }

    /**
     * Byte order is 'G H E F C D A B'
     * @param num long number
     * @return long number in little endian format
     */
    public static long LittleEndianWordSwap(long num){

        return (num & 0xffff000000000000L) >>> 48 |
                (num & 0x0000ffff00000000L) >>> 16 |
                (num & 0x00000000ffff0000L) << 16 |
                (num & 0x000000000000ffffL) << 48;
    }
}

三、数据还原

        使用包装类中的方法进行数据还原,如下例子。

public enum ByteOrder {
        //A B C D
        BIG_ENDIAN,
        //D C B A
        LITTLE_ENDIAN,
        //B A D C
        BIG_ENDIAN_WORD_SWAP,
        //C D A B
        LITTLE_ENDIAN_WORD_SWAP
    }


    public static void main(String[] args) {
        float f = 17.61373519F;
        int fi = Float.floatToIntBits(f);
        double d = 123456.78964531;
        long di = Double.doubleToLongBits(d);
        System.out.println("A B C D:" + Float.intBitsToFloat(fi));
        System.out.println("D C B A:" + Float.intBitsToFloat(ByteOrderUtils.LittleEndian(fi)));
        System.out.println("B A D C:" + Float.intBitsToFloat(ByteOrderUtils.BigEndianWordSwap(fi)));
        System.out.println("C D A B:" + Float.intBitsToFloat(ByteOrderUtils.LittleEndianWordSwap(fi)));
    }

        输出结果如下则,表示位运算正确。

A B C D:17.613735
D C B A:-3.598504E28
B A D C:-1.4940072E-31
C D A B:-9.001059E24

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值