数据处理方式

此方法适用于数据固定分类展示

假设单个文件有6百多万的数据量(按行列存储500*13202),数据按类别可以分为5类

先说结果,原始数据量31.6M,压缩后文件是3K

按如下步骤进行处理

1.将所有数据划分为5类

    List<Float> hResult = new ArrayList<>(500 * 13202);
    byte[] bytes = new byte[500 * 13202];
        for (int i = 500; i < 1000; i++) {
            for (int j = 0; j < 13202; j++) {
                // 存储数据,生成txt
                hResult.add(NumberUtil.round(hdata[i][j], 4).floatValue());
                // 将数据转换成byte[]
                bytes[t++] = FileUtil.getGrade(NumberUtil.round(hdata[i][j], 4).floatValue(), gradeArray, -1f);
            }
        }

    /**
     * 0- <0.1的数据
     * 1- 0.1=<x<0.2
     * 2- 0.2=<x<0.3
     * 3- 0.3=<x<0.4
     * 4- 0.4=<x
     * @param value 需要处理的值
     * @param gradeArray 类别
     * @param noDataValue 无效数据,可以指定,也可以不指定
     * @return
     */
    public static byte getGrade(float value, float[] gradeArray, float noDataValue) {
        if (value == noDataValue) {
            return 0;
        }
        byte num = 0;
        for (int index = 0; index < gradeArray.length; ++index) {
            if (index == gradeArray.length - 1) {
                if (value >= gradeArray[index]) {
                    num = (byte) (index + 1);
                }
            } else if (value >= gradeArray[index] && value < gradeArray[index + 1]) {
                num = (byte) (index + 1);
            }
        }
        return num;
    }

2.将分类后的数据进行压缩

    // 获取压缩后的数据
    List<Byte> compressByte = new ArrayList<>();
    FileUtil.compressData(compressByte, bytes);

    /**
     * @describe:加密算法,获取总的结果
     * @param:
     * @param: result 加密后的值
     * @param: dataArray 原始值
     * @return: void
     **/
    public static void compressData(List<Byte> result, byte[] dataArray) {
        byte num = dataArray[0];
        int count = 0;
        for (int i = 0; i < dataArray.length; i++) {
            byte data = dataArray[i];
            if ((int) data == (int) num) {
                ++count;
            } else {
                writeData(result, num, count);
                num = data;
                count = 1;
            }
        }
        if (count == dataArray.length) {
            writeData(result, num, count);
        }
    }
    /**
     * 解码的规律是以8位步长加载二进制作为一组,1组中从左数第一个不是1的是颜色组,颜色组右三位表示颜色,颜色个数的算法如下:
     * 1.第一个颜色组到下一个颜色组之间算 组数
     * 2.第一个颜色组中的数>>3然后<<7*(组数-组数所在位置(位置从1开始)) 得到最高位
     * 3.除颜色组外组数的值(无符号位与运算127)<<7*(组数-组数所在位置)
     * 4.最后一组的数也就是本身
     * 5.个数还需要和列进行比较,不能超过列数
     * byte数组1个字节,二进制占8位,颜色占3位
     * 01111 111 去除颜色位,按16进制解码,找到下一个
     */
    private static void writeData(List<Byte> result, byte value, int count) {
        if (count < 16) {
            byte num = (byte) ((count << 3) | value);
            result.add(num);
        } else if (count < 2048) {
            byte num1 = (byte) ((count >> 7 << 3) | value);
            result.add(num1);
            byte num2 = (byte) ((count & (int) Byte.MAX_VALUE) | 128);
            result.add(num2);
        } else if (count < 262144) {
            byte num1 = (byte) ((count >> 14 << 3) | value);
            result.add(num1);
            byte num2 = (byte) ((count >> 7 & (int) Byte.MAX_VALUE) | 128);
            result.add(num2);
            byte num3 = (byte) ((count & (int) Byte.MAX_VALUE) | 128);
            result.add(num3);
        } else if (count < 33554432) {
            byte num1 = (byte) ((count >> 21 << 3) | value);
            result.add(num1);
            byte num2 = (byte) ((count >> 14 & (int) Byte.MAX_VALUE) | 128);
            result.add(num2);
            byte num3 = (byte) ((count >> 7 & (int) Byte.MAX_VALUE) | 128);
            result.add(num3);
            byte num4 = (byte) ((count & (int) Byte.MAX_VALUE) | 128);
            result.add(num4);
        } else {
            if (count >= 1) {
                return;
            }
            byte num1 = (byte) ((count >> 28 << 3) | value);
            result.add(num1);
            byte num2 = (byte) ((count >> 21 & (int) Byte.MAX_VALUE) | 128);
            result.add(num2);
            byte num3 = (byte) ((count >> 14 & (int) Byte.MAX_VALUE) | 128);
            result.add(num3);
            byte num4 = (byte) ((count >> 7 & (int) Byte.MAX_VALUE) | 128);
            result.add(num4);
            byte num5 = (byte) ((count & (int) Byte.MAX_VALUE) | 128);
            result.add(num5);
        }
    }

3.存储压缩数据

    // 存储二进制数据
    String imageResultPath_h = "D:\\data\\cs.dat";
    DataOutputStream out_h = new DataOutputStream(cn.hutool.core.io.FileUtil.getOutputStream(imageResultPath_h));
    byte[] resultByte = new byte[compressByte.size()];
    for (int j = 0; j < compressByte.size(); j++) {
        resultByte[j] = compressByte.get(j);
    }
    out_h.write(resultByte, 0, compressByte.size());
    out_h.flush();
    out_h.close();

重点解释下writeData方法

writeData(List<Byte> result, byte value, int count)

result是最后的结果,value是类别值(0-4),count是类别的个数

byte 1字节在二进制中是8位 颜色位3位,数据标识占1位,value类别转化成二进制不超过3位,第一个字节先存储颜色位,颜色位占3位,数据和颜色字节区别是以每个字节中的第一位区别,颜色位字节第一位是0,数据位字节第一位是1

数据大小以n+4字节划分,n是7的倍数,0000,0000 000 0000 ,0000 000 0000 000 0000 .......,对应的int型数是最大值分别是15,2047,262143 .....

每次存储先从高位进行存储,每个字节是8位,每次位移是7的倍数,首位进行补充标识位,解析时间有规律可循

此方法进行数据传输即有加密的效果,又达到的数据量的压缩,后续经过改进可以适应很多数据类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值