精华内容
下载资源
问答
  • 请先参阅我的上篇文章:解析数据帧 android蓝牙数据帧解析 物联网数据帧解析本篇文章主要是针对数据帧解析而做的小工具,.本篇可以说是2.0版主要解决一个问题:把写死的截取位置变成动态获取的位置,能够做到即使修改...
    请先参阅我的上篇文章:解析数据帧 android蓝牙数据帧解析 物联网数据帧解析
    本篇文章主要是针对数据帧解析而做的小工具,.本篇可以说是2.0版
    主要解决一个问题:把写死的截取位置变成动态获取的位置,能够做到即使修改协议帧也能少改代码,快速更改。
    例如
    原来写String subdata = data.substring(2,4)
        @Field(value=ORI,location=1)
    现在String subdata;
    本次升级:
    1:优化代码,去除冗余
    2:属性值的解析类型,使用注解,名称为value的值,取消原来属性的默认值
    3:使用抽象方法返回值,替代原来主动给Pattern 和 ori_data赋值

    有了以上的优化,编写解析的bean会更清晰明了.

    使用方法如下:

    package com.gprs.blue.bean.frame.receive;
    
    import android.support.annotation.StringDef;
    
    
    public class TestBean extends BaseHarvesterBean<TestBean> {
    
        @FieldMeta1(location = 2,value = ORI)
        public String data1;
        @FieldMeta1(location = 6,value = BCD+REVERSE)
        public String data2;
        @FieldMeta1(location = 3,value = FLOAT1+REVERSE)
        public float data3;
        @FieldMeta1(location = 4,value = FLOAT1)
        public float data4;
        @FieldMeta1(location = 5,value = REVERSE+FLOAT2)
        public int data5;
      
        @Override
        public String getPattern() {
            return "111122334455557788999999";
        }
    
        @Override
        public TestBean mappingData() {
            return TestBean.this;
        }
    
        public TestBean(String data) {
    	super(data)
        }
     
        public String toStrings() {
            return "TestBean{" +
                    "data1='" + data1 + '\'' +
                    ", data2='" + data2 +
                    ", data3=" + data3 +
                    ", data4=" + data4 +
                    ", data5=" + data5 +
                    '}';
        }
        public static void main(String[] args) {
            System.out.println(new TestBean("0e0a0b0c0d01020304050607").toStrings(ONE));
        }
    
    }
    
    
    

    打印结果如下


    核心的BaseHarvesterBeanbean

    package com.xt.blueatuo.bean.parse;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 解析数据帧的通用类
     *1 如果只需要2个数据可以只定义2个变量
     *2 子类在java中反射的元素是无排序到,但是在android中按照首字母排序,在子类location中需要指定顺序
     */
    public abstract class BaseHarvesterBean<T extends BaseHarvesterBean<T>> {
        public boolean isParseError = true;
        /**
         * 要原始的字符串
         */
        public final String ORI = "ORI";
        /**
         * 要反转后的原始的字符串
         */
        public final String REVERSE = "REVERSE";
    
        public final String BCD = "BCD";
        /**
         * 保留小数 1:1位小数 2:两位小数...
         */
        public final String FLOAT1 = "FLOAT1";
        public final String FLOAT2 = "FLOAT2";
        public final String FLOAT3 = "FLOAT3";
        public final String FLOAT4 = "FLOAT4";
        /**
         * 待解析的原始数据
         */
        public String ori_data;
        /**
         * 解析规则的正则
         */
        public final String regex = "(.)\\1+";
    
        /**
         * 解析模版,长度和 ori_data 相等
         * example:aabbccccddddMMMM  or  1111223333445566(建议写数字,方便查找)
         */
        public String data_pattern;
        private final T subbean;
    
    
        /**
         * 返回data_pattern需要的值
         */
        public abstract String getPattern();
    
        /**
         * 返回子类自己
         */
        public abstract T mappingData();
    
        public BaseHarvesterBean(String data) {
            this.ori_data = data;
            this.data_pattern = getPattern();
            subbean = mappingData();
            mappingData(subbean);
        }
    
        /**
         * 构造函数调完后,可以再次解析数据
         * @param data
         */
        public void parseData(String data) {
            ori_data = data;
            mappingData(subbean);
        }
    
        /**
         * 映射模板
         * @param bean 待解析的bean
         */
        public void mappingData(T bean) {
            //校验模板和待解析数据是否为空 ,校验数据长度和模板长度是否相等
            if (ori_data == null || ori_data.length() == 0 ||
                    data_pattern == null || data_pattern.length() == 0 ||
                    ori_data.length() < data_pattern.length())
                return;
            //计算下标,并存储到tempLocation
            ArrayList<Integer> tempLocation = new ArrayList<>();
            tempLocation.add(0);
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(data_pattern);
            while (matcher.find()) {
                String group = matcher.group(0);
                tempLocation.add(tempLocation.get(tempLocation.size() - 1) + group.length());
            }
            fillData(tempLocation, bean);
        }
    
        /**
         * 数据赋值
         * @param location 模板对应的下标集合
         * @param bean     待赋值的bean
         */
        public void fillData(ArrayList<Integer> location, T bean) {
            try {
                Class<? extends BaseHarvesterBean> aClass = bean.getClass();
                Field[] fields = aClass.getDeclaredFields();
                List<Field> list = new ArrayList<>();
                for (Field field:fields) {
                    if (field.getAnnotation(FieldMeta.class) != null)
                        list.add(field);
                }
                Collections.sort(list, new Comparator<Field>() {
                    @Override
                    public int compare(Field lhs, Field rhs) {
                        return lhs.getAnnotation(FieldMeta.class).location()-rhs.getAnnotation(FieldMeta.class).location();
                    }
                });
                for (int i = 0; i < list.size(); i++) {
    //                // 获取属性注解的值
                    String anno_value = list.get(i).getAnnotation(FieldMeta.class).value();
    //                //获取属性类型
                    String type = list.get(i).getGenericType().toString();
    //                //可访问私有变量
                    list.get(i).setAccessible(true);
    //                //截取pattern后的值
                    String sub_data = ori_data.substring(location.get(i), location.get(i + 1));
    //
                    if (type.contains("String")) {//定义的类型为String
                        if (ORI.equals(anno_value) || BCD.equals(anno_value)) {//原始数据
                            list.get(i).set(bean, sub_data);
                        } else if (anno_value.length() ==10 && anno_value.contains(REVERSE)) {//反转的原始数据
                            list.get(i).set(bean, reverseData(sub_data));
                        }
                    } else if (type.contains("float")) {//定义的类型为float
                        if (anno_value.contains(REVERSE))
                            sub_data = reverseData(sub_data);
                        int temp = Integer.parseInt(sub_data, anno_value.contains(BCD)?10:16);
                        float f = 0f;
                        if (anno_value.contains("1")) {
                            f = Float.parseFloat(plusDot(temp, 1));
                        } else if (anno_value.contains("2")) {
                            f = Float.parseFloat(plusDot(temp, 2));
                        } else if (anno_value.contains("3")) {
                            f = Float.parseFloat(plusDot(temp, 3));
                        } else if (anno_value.contains("4")) {
                            f = Float.parseFloat(plusDot(temp, 4));
                        }
                            list.get(i).set(bean, f);
                    } else if (type.contains("int")) {
                        if (anno_value.contains(REVERSE))
                            sub_data = reverseData(sub_data);
                        int temp = Integer.parseInt(sub_data, anno_value.contains(BCD)?10:16);
                        list.get(i).set(bean, temp);
                     }
                }
                isParseError = false;
            } catch (Exception e) {
                isParseError = true;
                e.printStackTrace();
            }
        }
    
        /**
         * 高低位转换的工具 地址 反转
         *
         * @param data
         * @return
         */
        public static String reverseData(String data) {
            int length = data.length() / 2;
            String result = "";
            for (int i = 0; i < length; i++) {
                result += data.substring(data.length() - 2, data.length());
                data = data.substring(0, data.length() - 2);
            }
            return result;
        }
    
        /**
         * 给数据加小数点精确
         */
        public static String plusDot(int data, int mod) {
            String daString = String.valueOf(data);
            if (daString.length() <= mod) {
                int len = daString.length();
                for (int i = 0; i <= mod - len; i++)
                    daString = "0" + daString;
            }
            String begin = daString.substring(0, daString.length() - mod);
            String end = daString.substring(daString.length() - mod,
                    daString.length());
            return begin + "." + end;
        }
    
        /**
         * 是否可以转换为10进制
         * @return true:可以转换
         */
        public boolean isParseAble(String data) {
            return data.matches("\\d+");
        }
    
    
        /**
         * 给数据加小数点精确
         */
        public static String plusDot(String data, int mod, boolean needReverse, boolean isHex) {
            long val = Long.parseLong(data, isHex ? 16 : 10);
            if (needReverse) {
                val = Long.parseLong(reverseData(data), isHex ? 16 : 10);
            }
            String daString = String.valueOf(val);
            if (daString.length() <= mod) {
                int len = daString.length();
                for (int i = 0; i <= mod - len; i++)
                    daString = "0" + daString;
            }
            String begin = daString.substring(0, daString.length() - mod);
            String end = daString.substring(daString.length() - mod,
                    daString.length());
            return begin + "." + end;
        }
    
    }
    
    
    

    提供注解的类

    package com.xt.blueatuo.bean.parse;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * Created by admin on 2018/3/1.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD,ElementType.METHOD})
    public @interface FieldMeta {
        /**
         * 排序信息
         * @return
         */
        int location();
    
        /**
         * 值为BaseHarvesterBean 中定义到常量
         * @return
         */
        String value() default "";
    }

    本篇文字写的过于简单,请先看上篇文字。如果你有更好的办法,欢迎一起来次牛逼。




    展开全文
  • 当我看到需要改的代码时我傻眼了,请大家仔细看String data=”565224CA5FF298AAEE775369874178456123784561EEEEEEEEEEE248526549856784561239845613298456123AACCFF45612398546DDCC2398456123985623856...

    话说我们硬件部门修改了通信协议,我们不得已需要改动软件。当我看到需要改的代码时我傻眼了,请大家仔细看

    String         data=”565224CA5FF298AAEE775369874178456123784561EEEEEEEEEEE248526549856784561239845613298456123AACCFF45612398546DDCC2398456123985623856AACCBBFF23856239856235685623589562566AADDCC256EE6644892”;

    4String len1 = data.substring(22, 24);

    String len2 = data.substring(24, 26);

        if (data.length() >= totalLength && data.substring(18, 22).equalsIgnoreCase("d012")) {

    data = data.substring(0, totalLength);

    tv_nfjd.setText(orderThePriceOrFenjieDian(data.substring(26, 46), 1));

    tv_ndj.setText(orderThePriceOrFenjieDian(data.substring(46,70), 2));

            tv_njszq.setText(Integer.parseInt(data.substring(70, 72), 16) + "");

    if (data.substring(70, 72).equalsIgnoreCase("0C")) {

        tv_njszq.setText("哦哦");

    } else if (data.substring(70, 72).equalsIgnoreCase("03")) {

        tv_njszq.setText("品牌");

    } else {

        tv_njszq.setText("看看");

    }

    tv_njsr.setText(Util.delete0AtStrLeft(data.substring(72, 74)));

    tv_njsy.setText(Util.delete0AtStrLeft(data.substring(74, 76)));

      tv_flg.setText(data.substring(76, 78));

    String[] date = StringUtil.toStringByRadius(data.substring(78, 84), 2);

    tv_date.setText("20" + date[2] + "-" + date[1] + "-" + date[0]);

    tv_pfjd.setText(orderThePriceOrFenjieDian(data.substring(84, 104), 1));

    tv_pdj.setText(orderThePriceOrFenjieDian(data.substring(104, 128), 2));

            tv_pjszq.setText(Integer.parseInt(data.substring(128, 130), 16) + "");

    if (data.substring(128, 130).equalsIgnoreCase("0C")) {

        tv_pjszq.setText("ll");

    } else if (data.substring(128, 130).equalsIgnoreCase("03")) {

        tv_pjszq.setText("mm");

    } else {

        tv_pjszq.setText("hh");

    }

    tv_pjsr.setText(Util.delete0AtStrLeft(data.substring(130, 132)));

    tv_pjsy.setText(Util.delete0AtStrLeft(data.substring(132, 134)));

        }

     我的任务是修改红色的部分,把这个数据帧截取出来在按照文档解析后显示。看起来很简单对吧。这个数据很短,也就50多个字节,改完这个也就是几十分钟。但是这次运气好,下次遇到个几百字节的文件,那不是要抓狂了!一般来说一个文件有几百个字节也是很正常的,硬件那里经常改协议也是很正常的,那别人总是虐待我们,我们真的没有办法,只能辛苦搬砖?我不,我TMD不服!于是乎我发明了改变世界的解析方法! 我解决这个问题只需短短几行代码,我不在手动去分割字符串,而是用写个pattern,动态计算并分割字符串,如果需要修改,分割内容,只需修改pattern就行了,修改一下只需几秒钟.

    一句话说明我的办法:定义一个叠词pattern(AA1111BBFF),使用正则表达式分割叠词,得到分割的长度和下标然后分割数据。

    使用方法:

    第一步:复制BaseHarvesterBean,复制FieldMeta

    第二步:写个类继承 BaseHarvesterBean,泛型为子类类型,并赋值ori_data(父类定义好的原始数据变量),data_pattern(父类定义的解析模板变量)解析模板以叠词形式出现(AA114444)

    先看个简单的demo

    public class TestBean extends BaseHarvesterBean<TestBean> {
    
        //父类中定义的模板变量,
    	//data_pattern
        //父类中定义的原始数据变量,
    	//ori_data
        //location=2表示当前data1在data_pattern= "111122334455667788999999"中
    	//需要截取第二个叠词(22)对应的数据 ori_data = "0e0a0b0c0d01020304050607";
    	//位置为0b,location=1 表示截取ori_data数据0e0a,ORI为父类中常量
        @FieldMeta(location = 2)
    	public String data1 = ORI;
        @FieldMeta(location = 1)
        public String data2 = REVERSE_ORI;
        @FieldMeta(location = 3)
        public float data3 = BCD_FLOAT_1;
        @FieldMeta(location = 9)
        public float data4 = BCD_FLOAT_4;
        @FieldMeta(location = 5)
        public float data5 = REVERSE_BCD_FLOAT_1;
        @FieldMeta(location = 6)
        public float data6 = REVERSE_HEX_FLOAT_2;
        @FieldMeta(location = 7)
        public float data7 = HEX_FLOAT_1;
        @FieldMeta(location = 8)
        public int data8 = HEX_INT;
        @FieldMeta(location = 4)
        public int data9 = REVERSE_HEX_INT;
    
    
    
        public TestBean() {
            data_pattern = "111122334455667788999999";
            ori_data =     "0e0a0b0c0d01020304050607";
    		//data1 截取的位置为0e0a
            mappingData(this);
        }
    
    
        @Override
        public String toString() {
            return "TestBean{" +
                    "data1='" + data1 + '\'' +
                    ", data2='" + data2 +
                    ", data3=" + data3 +
                    ", data4=" + data4 +
                    ", data5=" + data5 +
                    ", data6=" + data6 +
                    ", data7=" + data7 +
                    ", data8=" + data8 +
                    ", data9=" + data9 +
                    '}';
        }
        public static void main(String[] args) {
            System.out.println(new TestBean().toString());
        }
    
    }

    注意:

    1  继承BaseHarvesterBean泛型为子类的类型

    2 :这里只需要定义需要的数据名,数据类型,数据的默认值为父类当中的,也就是要解析的方式.

    3:调用父类中的方法mappingData(this)

     

     原理:

    1:先定义data_pattern 这个是需要截取字符串的规则,必须用叠词表示 例如 AABBFFFF 或者11AAMMMMdddd== 可以使用任意符号字母数字,都需要成对出现

    2:定义子类属性例如 String a = ORI  ,a必须赋值且为父类中定义好的常量,常量中包含解析(16进制的转换)的方式

    3:给ori_data赋16进制  例如值为FF08C001

     4:父类中拿到ori_data 的值,把定义好的data_pattern 使用正则表达式去分割叠词,之后把分割的长度计算出来存在ArrayList当中,也就是需要截取ori_data的下标.根据这些下标,就可以截取字符串了.

    5:然后使用反射获取子类中属性的默认值,根据提前定义好的默认值,把截取字符串的再相应的解析出来赋值给子类.


    FieldMeta代码如下

    /**
     * Created by admin on 2018/3/1.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD,ElementType.METHOD})
    public @interface FieldMeta {
        /**
         * 排序信息
         * @return
         */
        int location() default 0;
    
    }


    BaseHarvestBean代码如下:

    package com.gprs.blue.bean.frame.receive;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * Created by admin on 2018/2/6.
     * 解析数据帧的通用类
     *
     * 如果只需要2个数据可以只定义2个变量
     * 子类在java中反射的元素是无排序到,但是在android中按照首字母排序,所以在定义元素名称时需要排好序
     * example
             public   String switch_status = ORI;
             public String enable = ORI;
             String cSwitch_status;
     */
    
    public class BaseHarvesterBean<T extends BaseHarvesterBean<T>> {
        /**
         * 要原始的字符串
         */
        public final String ORI = "";
        /**
         * 要反转后的原始的字符串
         */
        public final String REVERSE_ORI = "reverse";
        /**
         * 16进制转化为10进制整数 (子类可不赋值)
         */
        public final int HEX_INT = 0;
        /**
         * 反转后16进制转换为10进制整数
         */
        public final int REVERSE_HEX_INT = 11;
        /**
         * 直接10进制整数
         */
        public final int BCD_INT = 12;
        /**
         * 反转后直接10进制整数 BCD
         */
        public final int REVERSE_BCD_INT = 13;
    
        /**
         * BCD取整转float保留1位小数 BCD
         */
        public final float BCD_FLOAT_1 = 1.1f;
        /**
         * BCD取整转float保留2位小数 BCD
         */
        public final float BCD_FLOAT_2 = 1.2f;
        /**
         * BCD取整转float保留3位小数 BCD取整转float
         */
        public final float BCD_FLOAT_3 = 1.3f;
        /**
         * BCD取整转float保留4位小数 BCD
         */
        public final float BCD_FLOAT_4 = 1.4f;
        /**
         * 反转后以BCD_转10进制,并转float保留4位小数
         */
        public final float REVERSE_BCD_FLOAT_1 = 4.1f;
        /**
         * 反转后以BCD_转10进制,并转float保留4位小数
         */
        public final float REVERSE_BCD_FLOAT_2 = 4.2f;
        /**
         * 反转后以BCD_转10进制,并转float保留4位小数
         */
        public final float REVERSE_BCD_FLOAT_3 = 4.3f;
        /**
         * 反转后以BCD_转10进制,并转float保留4位小数
         */
        public final float REVERSE_BCD_FLOAT_4 = 4.4f;
        /**
         * 反转后以16进制转10进制转float保留1位小数
         */
        public final float REVERSE_HEX_FLOAT_1 = 3.1f;
        /**
         * 反转后以16进制转10进制转float保留2位小数
         */
        public final float REVERSE_HEX_FLOAT_2 = 3.2f;
        /**
         * 反转后以16进制转10进制转float保留3位小数
         */
        public final float REVERSE_HEX_FLOAT_3 = 3.3f;
        /**
         * 反转后以16进制转10进制转float保留4位小数
         */
        public final float REVERSE_HEX_FLOAT_4 = 3.4f;
        /**
         * 反转以后16进制转10进制,并转float保留1位小数
         */
        public final float HEX_FLOAT_1 = 2.1f;
        /**
         * 反转以,16进制转10进制,并转float保留2位小数
         */
        public final float HEX_FLOAT_2 = 2.2f;
        /**
         * 反转以,16进制转10进制,并转float保留3位小数
         */
        public final float HEX_FLOAT_3 = 2.3f;
        /**
         * 反转以,16进制转10进制,并转float保留4位小数
         */
        public final float HEX_FLOAT_4 = 2.4f;
    
        /**
         * 待解析的原始数据
         */
        public String ori_data;
        /**
         * 解析规则的正则
         */
        public final String regex = "(.)\\1+";
    
        /**
         * 解析模版,长度和{@link ori_data}相等
         * example:aabbccccddddMMMM  or  1111223333445566(建议写数字,方便查找)
         */
        public String data_pattern;
    
        /**
         * 映射模板
         *
         * @param bean 待解析的bean
         */
        public void mappingData(T bean) {
            //校验模板和待解析数据是否为空 ,校验数据长度和模板长度是否相等
            if (ori_data == null || ori_data.length() == 0 ||
                    data_pattern == null || data_pattern.length() == 0 ||
                    ori_data.length() < data_pattern.length())
                return;
            ArrayList<Integer> tempLocation = new ArrayList<>();
            tempLocation.add(0);
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(data_pattern);
            while (matcher.find()) {
                String group = matcher.group(0);
                tempLocation.add(tempLocation.get(tempLocation.size() - 1) + group.length());
            }
            fillData(tempLocation, bean);
        }
    
        /**
         * 数据赋值
         *
         * @param location 模板对应的下标集合
         * @param bean     待赋值的bean
         */
        public void fillData(ArrayList<Integer> location, T bean) {
            try {
                Class<? extends BaseHarvesterBean> aClass = bean.getClass();
                Field[] fields = aClass.getDeclaredFields();
                List<Field> list = new ArrayList<>();
                for (Field field:fields) {
                    if (field.getAnnotation(FieldMeta.class) != null)
                        list.add(field);
                }
                Collections.sort(list, new Comparator<Field>() {
                    @Override
                    public int compare(Field lhs, Field rhs) {
                        return lhs.getAnnotation(FieldMeta.class).location()-rhs.getAnnotation(FieldMeta.class).location();
                    }
                });
                for (int i = 0; i < fields.length; i++) {
                    // 获取属性的值
                    Object data_value = list.get(i).get(bean);
                    //获取属性类型
                    String type = list.get(i).getGenericType().toString();
                    //可访问私有变量
                    list.get(i).setAccessible(true);
                    String sub_data = ori_data.substring(location.get(i), location.get(i + 1));
                    if (type.equals("class java.lang.String")) {
                        String temps = (String) data_value;
                        if (temps == null || temps.length() == 0) {//原始数据
                            list.get(i).set(bean, sub_data);
                        } else if (temps.equals(REVERSE_ORI)) {//反转后原始数据
                            list.get(i).set(bean, reverseData(sub_data));
                        }
                    } else if (type.equals("int")) {
                        int temps = (int) data_value;
                        if (temps == HEX_INT) {//转10进制
                            list.get(i).set(bean, Integer.parseInt(sub_data, 16));
                        } else if (temps == REVERSE_HEX_INT) {//反转后转10进制
                            list.get(i).set(bean, Integer.parseInt(reverseData(sub_data), 16));
                        } else if (temps == BCD_INT) {//直接转10进制
                            list.get(i).set(bean, isParseAble(sub_data) ? Integer.parseInt(sub_data) : 0);
                        } else if (temps == REVERSE_BCD_INT) {//反转后直接转10进制
                            list.get(i).set(bean, isParseAble(sub_data) ? Integer.parseInt(reverseData(sub_data)) : 0);
                        }
                    } else if (type.equals("float")) {
                        float temps = (float) data_value;
                        if (temps == BCD_FLOAT_1) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 1, false, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == BCD_FLOAT_2) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 2, false, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == BCD_FLOAT_3) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 3, false, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == BCD_FLOAT_4) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 4, false, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_BCD_FLOAT_1) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 1, true, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_BCD_FLOAT_2) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 2, true, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_BCD_FLOAT_3) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 3, true, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_BCD_FLOAT_4) {
                            float f = isParseAble(sub_data) ?
                                    Float.parseFloat(plusDot(sub_data, 4, true, false))
                                    : 0;
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_HEX_FLOAT_1) {
                            float f = Float.parseFloat(plusDot(sub_data, 1, true, true));
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_HEX_FLOAT_2) {
                            float f = Float.parseFloat(plusDot(sub_data, 2, true, true));
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_HEX_FLOAT_3) {
                            float f = Float.parseFloat(plusDot(sub_data, 3, true, true));
                            list.get(i).set(bean, f);
                        } else if (temps == REVERSE_HEX_FLOAT_4) {
                            float f = Float.parseFloat(plusDot(sub_data, 4, true, true));
                            list.get(i).set(bean, f);
                        } else if (temps == HEX_FLOAT_1) {
                            float f = Float.parseFloat(plusDot(sub_data, 1, false, true));
                            list.get(i).set(bean, f);
                        } else if (temps == HEX_FLOAT_2) {
                            float f = Float.parseFloat(plusDot(sub_data, 2, false, true));
                            list.get(i).set(bean, f);
                        } else if (temps == HEX_FLOAT_3) {
                            float f = Float.parseFloat(plusDot(sub_data, 3, false, true));
                            list.get(i).set(bean, f);
                        } else if (temps == HEX_FLOAT_4) {
                            float f = Float.parseFloat(plusDot(sub_data, 4, false, true));
                            list.get(i).set(bean, f);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 高低位转换的工具 地址 反转
         *
         * @param data
         * @return
         */
        public static String reverseData(String data) {
            int length = data.length() / 2;
            String result = "";
            for (int i = 0; i < length; i++) {
                result += data.substring(data.length() - 2, data.length());
                data = data.substring(0, data.length() - 2);
            }
            return result;
        }
    
        /**
         * 给数据加小数点精确
         */
        public static String plusDot(int data, int mod) {
            String daString = String.valueOf(data);
            if (daString.length() <= mod) {
                int len = daString.length();
                for (int i = 0; i <= mod - len; i++)
                    daString = "0" + daString;
            }
            String begin = daString.substring(0, daString.length() - mod);
            String end = daString.substring(daString.length() - mod,
                    daString.length());
            return begin + "." + end;
        }
    
        /**
         * 是否可以转换为10进制
         * @return true:可以转换
         */
        public boolean isParseAble(String data) {
            return data.matches("\\d+");
        }
    
    
        /**
         * 给数据加小数点精确
         */
        public static String plusDot(String data, int mod, boolean needReverse, boolean isHex) {
            long val = Long.parseLong(data, isHex ? 16 : 10);
            if (needReverse) {
                val = Long.parseLong(reverseData(data), isHex ? 16 : 10);
            }
            String daString = String.valueOf(val);
            if (daString.length() <= mod) {
                int len = daString.length();
                for (int i = 0; i <= mod - len; i++)
                    daString = "0" + daString;
            }
            String begin = daString.substring(0, daString.length() - mod);
            String end = daString.substring(daString.length() - mod,
                    daString.length());
            return begin + "." + end;
        }
    
    }
    
    
    




    允许我再B刀两句,data_pattern模版叠词的顺序要和子类全局变量的顺序一致 例如data_pattern =112233 子类全局变量为

     string a

     float b

    int c

    也就是说11截取后复制给子类a复制,22截取后赋值给b

    展开全文
  • 工作中经常遇到需要在数据流中提取数据帧的任务。这种数据帧一般以某种特定数据序列表示开始(例如0xa5,0x5a)和结束(0xb5, 0x5b),起始标记间的数据为帧有效数据。为了完成这一任务,特包装了一个简易的解析类,供在...

    工作中经常遇到需要在数据流中提取数据帧的任务。这种数据帧一般以某种特定数据序列表示开始(例如0xa5,0x5a)和结束(0xb5, 0x5b),起始标记间的数据为帧有效数据。为了完成这一任务,特包装了一个简易的解析类,供在性能要求不高场合使用。

    解析类代码如下

     1 template <typename T>
     2 class FrameParser
     3 {
     4 public:
     5     FrameParser(const std::vector<T> &headTag, const std::vector<T> &tailTag) : frameHeadTag(headTag), frameTailTag(tailTag){
     6     }
     7 
     8     template<class It>
     9     void append(It f, It l) {
    10         buffer.insert(buffer.end(), f, l);
    11     }
    12     void append(const std::vector<T> &data) {
    13         buffer.insert(buffer.end(), data.cbegin(), data.cend());
    14     }
    15 
    16     void parse(std::vector<std::vector<T>> &frames)
    17     {
    18         auto it_p0{ buffer.cbegin() };
    19         auto it_p1{ it_p0 };
    20         while (true)
    21         {
    22             it_p1 = it_p0;
    23             it_p0 = std::search(it_p0, buffer.cend()
                          , frameTailTag.cbegin(), frameTailTag.cend());
    24 if (it_p0 == buffer.cend()) { 25 break; 26 } 27 28 if (std::search(it_p1, it_p0, frameHeadTag.cbegin(), frameHeadTag.cend()) != it_p0)
             {
    29 frames.emplace_back(it_p1+ frameHeadTag.size() , it_p0 ); 30 } 31 std::advance(it_p0, frameTailTag.size()); 32 } 33 34 tempBuffer.insert(tempBuffer.end(), it_p1, buffer.cend()); 35 std::swap(buffer, tempBuffer); 36 tempBuffer.clear(); 37 } 38 39 private: 40 const std::vector<T> frameHeadTag; 41 const std::vector<T> frameTailTag; 42 std::vector<T> buffer; 43 std::vector<T> tempBuffer; 44 };

     

    使用测试代码如下

     1     FrameParser<std::uint8_t> parser{{ 0xa5, 0x5a }, { 0xb5, 0x5b }};
     2     std::vector<std::vector<std::uint8_t>> frames;    
     3 
     4     parser.append({
     5         0x01, 0x02, 0x03, 0xb5, 0x5b
     6         , 0xa5, 0x5a, 0x04, 0x05, 0x06, 0x07, 0xb5, 0x5b
     7         , 0xa5, 0x5a, 0x08, 0x09, 0x0a
     8     });
     9     parser.parse(frames);
    10 
    11     parser.append({ 0x0b, 0xb5, 0x5b, 0xa5, 0x5a, 0x0c });
    12     parser.parse(frames);
    13 
    14     parser.append({ 0x0b, 0xb5 });
    15     parser.parse(frames);

     

    转载于:https://www.cnblogs.com/thinkway/p/7874086.html

    展开全文
  • 解析串口-接收完整数据帧

    万次阅读 2016-05-23 16:48:35
    在linux下编写串口通讯程序,采用select...程序实际运行情况:两次读完:四次读完:为了解决不能接收完整数据帧的问题,借鉴了网友的例子,并进行了一些改动:现在的效果:下面是程序代码:#include "smartlight.h"int

    在linux下编写串口通讯程序,采用select监听串口的可读事件,一旦可读,调用read。但是我们会发现,read一次得到的数据通常不是完整的一个数据帧。

    比如完整数据帧为

    这里写图片描述

    但是实际上需要read多次才能完全读到。

    程序实际运行情况:

    两次读完:

    这里写图片描述

    四次读完:

    这里写图片描述

    为了解决不能接收完整数据帧的问题,借鉴了网友的例子,并进行了一些改动:

    现在的效果:

    这里写图片描述

    下面是程序代码:

    #include "smartlight.h"
    
    int portfd = -1;
    void print_frame(const char *desc,uint8_t *buf,int size);
    void getCompleteFrame(uint8_t *inBuf,int inCnt,uint8_t *outBuf,int *destCnt,int *readStatus);
    void *monitor_serial_readable(void *arg);
    
    int main(int argc,char *argv[])
    {
        int nret;
        pthread_t wtid;
        /* open serial port */
        portfd = open_port();
        /* set serial port */
        set_opt(portfd,57600);
    
        nret = pthread_create(&wtid,NULL,monitor_serial_readable,NULL);
        if(nret != 0)
        {
            DEBUG_ERR(create thread failed);
            exit(-1);
        }
        nret = pthread_join(wtid,NULL);
        if(nret != 0)
        {
            DEBUG_ERR(join thread failed);
            exit(-1);
        }
        close(portfd);
    
        return 0;
    }
    
    void getCompleteFrame(uint8_t *inBuf,int inCnt,uint8_t *outBuf,int *destCnt,int *readStatus)
    {
        int i;
        for(i=0; i<inCnt; i++)
        {
            if(inBuf[i] == 0x11 && inBuf[i+2] == 0x00 && inBuf[i+3] == 0x00)//header
            {
                outBuf[(*destCnt)++] = inBuf[i];
                *readStatus = 1;
                //print_frame("header",dest,dest_cnt);
                continue;
            }
            if(*readStatus == 1)//body
            {
                outBuf[(*destCnt)++] = inBuf[i];    
                //print_frame("body",dest,dest_cnt);
            }
            if(*destCnt == outBuf[1])//tail
            {
                print_frame("tail",outBuf,*destCnt);
                *readStatus = 0;
                *destCnt = 0;
                memset(outBuf,-1,sizeof(outBuf));
                memset(inBuf,0,sizeof(inBuf));
                continue;
            }
        }
    }
    
    void *monitor_serial_readable(void *arg)
    {
        int rc,i,nread=0;
        fd_set rset;
        struct timeval tv;
        uint8_t buf[1024] = {0};
        uint8_t dest[1024]={0};
        int read_status = 0;
        int dest_cnt = 0;
    
        while(1)
        {
            FD_ZERO(&rset);
            FD_SET(portfd,&rset);
    
            tv.tv_sec = 5;
            tv.tv_usec = 0;
    
            rc = select(portfd+1,&rset,NULL,NULL,&tv);
            if(rc == -1)
            {
                DEBUG_ERR(select error in thread);
                continue;
            }
            if(rc == 0)
            {
                DEBUG_INFO(select timeout in thread);
                continue;
            }
            else
            {
                nread = read(portfd,buf,sizeof(buf));   
                if(nread == -1)
                {
                    perror("read");
                    usleep(100*1000);
                    continue;
                }
                if(nread == 0)
                {
                    printf("nread==0\n");
                    usleep(100*1000);
                    continue;
                }
                printf("nread = %d\n",nread);
                getCompleteFrame(buf,nread,dest,&dest_cnt,&read_status);
            }
        }//END_while
    }
    
    void print_frame(const char *desc,uint8_t *buf,int size)
    {
        int i;
    
        printf(RED"[%s] [LEN=%d]"COLOR_END,desc,size);
        for(i=0; i<size; i++)
        {
            printf(BLUE"[%.2x]"COLOR_END,buf[i]);
        }
        printf("\n");
    }
    
    展开全文
  • 1. 简介 图像修复是对图像中缺失的...本文对Deep Video Inpainting这篇论文的要点和代码进行解析。 论文对视频的缺失区域进行填补,需要解决的问题有2个:1)对单图片进行修复;2)保证修复视频的连续性。同一视...
  • 前言 大家好,我是川楠,前段时间在芯吧客的问答频道上回答了好几个关于串口数据帧解析的问题。想想当初我学习单片机的时候,也在这个地方折腾了不少时间,看过了很多的代码,也尝试了多种写法。 实现串口数据帧断帧...
  • java代码: public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main...
  • 前言 大家好,我是川楠,前段时间在芯吧客的问答频道上回答了好几个关于串口数据帧解析的问题。想想当初我学习单片机的时候,也在这个地方折腾了不少时间,看过了很多的代码,也尝试了多种写法。 实现串口数据帧断帧...
  • 收集了几个对MP3文件格式说明比较详细的网页,并附带上JAVA版本的源代码.可实现每次读取一帧数据.
  • 这里写目录标题源码下载1 OFDM参数2 数据集参数3 莱斯信道的参数4 数据存储的思路4 运行 ...接受端一帧数据就是2×(256+64)=2*320 = 640,2表示IQ两个信号,640长度的帧数据作为数据集的每训练数据 3 莱
  • 什么是数据解析二、实例代码1.实例代码2.运行结果 前言 上篇中与小伙伴们分享一下数据通信过程中数据的转义,今天来它的后篇——数据解析。 一、关于转义与解析的说明 1.为什么要进行转义与解析 数据通信中...
  • 大部分应用程序协议是根据由字段序列组成的离散信息定义的,其中每个字段中都包含了一段以位序列编码(即二进制字节编码,也可以使用基于文本编码的方式,但常用协议如:TCP、UDP、HTTP等在传输数据时,都是以位序列...
  • MODBUS-RTU数据帧格式、报文实例

    万次阅读 多人点赞 2017-10-07 14:13:16
    MODBUS-RTU报文模型 设备地址 ...一个报文就是一帧数据,一个数据帧就一个报文: 指的是一串完整的指令数据,就像上面的一串数据。主机对从机写数据操作如果单片机接收到一个报文那么就对报文进行解析
  • 大部分应用程序协议是根据由字段序列组成的离散信息定义的,其中每个字段中都包含了一段以位序列编码(即二进制字节编码,也可以使用基于文本编码的方式,但常用协议如:TCP、UDP、HTTP等在传输数据时,都是以位序列...
  • 今天与小伙伴们分享一下数据通信过程中数据的转义与解析的一种实现方式,今天先进行转义部分的代码实现,后面再写一篇数据解析文章。 一、关于转义与解析的说明 1.为什么要进行转义与解析 数据通信中需要对有特定...
  • 大部分应用程序协议是根据由字段序列组成的离散信息定义的,其中每个字段中都包含了一段以位序列编码(即二进制字节编码,也可以使用基于文本编码的方式,但常用协议如:TCP、UDP、HTTP等在传输数据时,都是以位序列...
  • 大部分应用程序协议是根据由字段序列组成的离散信息定义的,其中每个字段中都包含了一段以位序列编码(即二进制字节编码,也可以使用基于文本编码的方式,但常用协议如:TCP、UDP、HTTP等在传输数据时,都是以位序列...
  • 我们先用王者荣耀这款游戏引入一下,王者可是撩妹利器,哈哈,就像你有两部手机(安卓和苹果),带妹的时候大概率会用苹果,因为游戏体验方面苹果要优于安卓,带妹的时候不掉,不卡顿,不闪退,要操作有操作,有...
  • 解析 H.264 NAL Unit 类型

    千次阅读 2013-05-16 08:28:42
    解析 H.264 NAL Unit 类型的代码: ////////////////////////////////////////////////////////////////////////// // 功能: 从 Nal Unit 数据中获取类型 // 读取字节结构体 typedef struct bs_t_T { ...
  • 这个过程大致分成两步,第一步是读取excel文件,使用pd.ExcelFile方法,可以存储在类似file的变量当中,第二步是把file中的内容用file.parse()方法解析至data中,转换成一个DataFrame数据帧。 具体代码如下: import...
  • 字节流数据解析

    2019-12-26 13:43:49
    近期在做linux串口的数据通讯时,发生了让人头疼的丢包,后分析解析代码发现一旦数据段中含有头便会解析不到数据,通过一上午的调试,写了一个新的解析。 #include <stdio.h> //头 长度 命令 数据 ...
  • 376.1协议解析代码

    2018-01-02 09:43:53
    //控制域 D3~D0 功能码PRM=1:功能码11【请求∕响应,请求2级数据】,功能码10【请求∕响应,请求1级数据】 //地址域内容 public string A1;//行政区划码 public string A2;//终端地址 public string MSA;/...
  • 总体思路输入数据:rgb图及时间戳,深度图及时间戳初始化参考和当前都设置为输入插入关键(含frame及其id)提取特征点计算描述子求参考中特征点的3D点坐标(setRef3DPoints,参考像素的3D坐标,由相机...
  • Java基础 第一个Java程序 ... 代码: public class Hello { public static void main(String args[]) { System.out.println("Hello world !"); } } // 编译 javac Hello.java // 运行 java ...
  • 语义解析的示例如下所示 安装 该项目基于python == 3.7.9和库构建。 此外,它使用了一些软件包。 $ pip install dynet==2.0.3 $ pip install nltk==3.5 $ python -m nltk.downloader averaged_perceptron_tagger...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 292
精华内容 116
关键字:

解析数据帧代码