import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Base64;
import java.io.ByteArrayOutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class JsonUtil {


    public static void main(String[] args) throws IOException {

        String jsonData = "{\n" +
                "  \"code\": 0,\n" +
                "  \"data\": [\n" +
                "    {\n" +
                "      \"createTime\": 1717053232000,\n" +
                "      \"updateTime\": 1717053232000,\n" +
                "      \"creator\": \"晨丰科技\",\n" +
                "      \"updater\": \"晨丰科技\",\n" +
                "      \"deleted\": false,\n" +
                "      \"id\": 358,\n" +
                "      \"name\": \"2024年5月30日2\",\n" +
                "      \"pieceRate\": 0.001,\n" +
                "      \"pieceType\": 3,\n" +
                "      \"type\": 1,\n" +
                "      \"isCustom\": true,\n" +
                "      \"isDealer\": false,\n" +
                "      \"sort\": 1000,\n" +
                "      \"hourCapacity\": 0.001,\n" +
                "      \"unit\": \"件\",\n" +
                "      \"isEnabled\": true,\n" +
                "      \"prepareTime\": 0,\n" +
                "      \"description\": \"2024年5月30日2\",\n" +
                "      \"organId\": 1\n" +
                "    },\n" +
                "    {\n" +
                "      \"createTime\": 1717053193000,\n" +
                "      \"updateTime\": 1717053193000,\n" +
                "      \"creator\": \"晨丰科技\",\n" +
                "      \"updater\": \"晨丰科技\",\n" +
                "      \"deleted\": false,\n" +
                "      \"id\": 357,\n" +
                "      \"name\": \"2024年5月30日\",\n" +
                "      \"pieceRate\": 0.001,\n" +
                "      \"pieceType\": 2,\n" +
                "      \"type\": 7,\n" +
                "      \"isCustom\": true,\n" +
                "      \"isDealer\": false,\n" +
                "      \"sort\": 1000,\n" +
                "      \"hourCapacity\": 0.001,\n" +
                "      \"unit\": \"件\",\n" +
                "      \"isEnabled\": true,\n" +
                "      \"prepareTime\": 0,\n" +
                "      \"description\": \"2024年5月30日\",\n" +
                "      \"organId\": 1\n" +
                "    },\n" +
                "    {\n" +
                "      \"createTime\": 1716191704000,\n" +
                "      \"updateTime\": 1716280724000,\n" +
                "      \"creator\": \"晨丰科技\",\n" +
                "      \"updater\": \"晨丰科技\",\n" +
                "      \"deleted\": false,\n" +
                "      \"id\": 355,\n" +
                "      \"name\": \"测试编辑dvdvd工序\",\n" +
                "      \"pieceRate\": 985,\n" +
                "      \"pieceType\": 7,\n" +
                "      \"type\": 2,\n" +
                "      \"isCustom\": true,\n" +
                "      \"isDealer\": false,\n" +
                "      \"sort\": 1001,\n" +
                "      \"hourCapacity\": 41,\n" +
                "      \"unit\": \"亩\",\n" +
                "      \"isEnabled\": true,\n" +
                "      \"prepareTime\": 0,\n" +
                "      \"description\": \"测试test69dvdvd9\",\n" +
                "      \"organId\": 1\n" +
                "    }\n" +
                "  ],\n" +
                "  \"msg\": \"\"\n" +
                "}";

        String s = zipString(jsonData);
        System.out.println(s.getBytes());
        System.out.println(s.length());
        System.out.println(jsonData.length());


        String compress = compress(jsonData);
        System.out.println(compress);
        System.out.println(compress.length());


    }

    /**
     * 压缩
     */
    public static String zipString(String unzipString) {
        /**
         *     https://www.yiibai.com/javazip/javazip_deflater.html#article-start
         *     0 ~ 9 压缩等级 低到高
         *     public static final int BEST_COMPRESSION = 9;            最佳压缩的压缩级别。
         *     public static final int BEST_SPEED = 1;                  压缩级别最快的压缩。
         *     public static final int DEFAULT_COMPRESSION = -1;        默认压缩级别。
         *     public static final int DEFAULT_STRATEGY = 0;            默认压缩策略。
         *     public static final int DEFLATED = 8;                    压缩算法的压缩方法(目前唯一支持的压缩方法)。
         *     public static final int FILTERED = 1;                    压缩策略最适用于大部分数值较小且数据分布随机分布的数据。
         *     public static final int FULL_FLUSH = 3;                  压缩刷新模式，用于清除所有待处理的输出并重置拆卸器。
         *     public static final int HUFFMAN_ONLY = 2;                仅用于霍夫曼编码的压缩策略。
         *     public static final int NO_COMPRESSION = 0;              不压缩的压缩级别。
         *     public static final int NO_FLUSH = 0;                    用于实现最佳压缩结果的压缩刷新模式。
         *     public static final int SYNC_FLUSH = 2;                  用于清除所有未决输出的压缩刷新模式; 可能会降低某些压缩算法的压缩率。
         */

        //使用指定的压缩级别创建一个新的压缩器。
        Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
        //设置压缩输入数据。
        deflater.setInput(unzipString.getBytes());
        //当被调用时，表示压缩应该以输入缓冲区的当前内容结束。
        deflater.finish();

        final byte[] bytes = new byte[256];
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);

        while (!deflater.finished()) {
            //压缩输入数据并用压缩数据填充指定的缓冲区。
            int length = deflater.deflate(bytes);
            outputStream.write(bytes, 0, length);
        }
        //关闭压缩器并丢弃任何未处理的输入。
        deflater.end();
        return Base64.getEncoder().encodeToString(outputStream.toByteArray());
    }

    /**
     * 解压缩
     */
    public static String unzipString(String zipString) {
        byte[] decode = Base64.getDecoder().decode(zipString);

        //创建一个新的解压缩器  https://www.yiibai.com/javazip/javazip_inflater.html

        Inflater inflater = new Inflater();
        //设置解压缩的输入数据。
        inflater.setInput(decode);
        final byte[] bytes = new byte[256];
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256);
        try {
            //finished() 如果已到达压缩数据流的末尾，则返回true。
            while (!inflater.finished()) {
                //将字节解压缩到指定的缓冲区中。
                int length = inflater.inflate(bytes);
                outputStream.write(bytes, 0, length);
            }
        } catch (DataFormatException e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭解压缩器并丢弃任何未处理的输入。
            inflater.end();
        }

        return outputStream.toString();
    }


    // 使用 GZIP 进行压缩
    public static String compress(String str) throws IOException {
        if (null == str || str.length() <= 0) {
            return str;
        }
        // 创建一个新的输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 使用默认缓冲区大小创建新的输出流
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        // 将字节写入此输出流
        gzip.write(str.getBytes("utf-8")); // 因为后台默认字符集有可能是GBK字符集，所以此处需指定一个字符集
        gzip.close();
        // 使用指定的 charsetName，通过解码字节将缓冲区内容转换为字符串
        return out.toString("ISO-8859-1");
    }


    // 解压缩
    public static String unCompress(String str) throws IOException {
        if (null == str || str.length() <= 0) {
            return str;
        }
        // 创建一个新的输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 创建一个 ByteArrayInputStream，使用 buf 作为其缓冲 区数组
        ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
        // 使用默认缓冲区大小创建新的输入流
        GZIPInputStream gzip = new GZIPInputStream(in);
        byte[] buffer = new byte[256];
        int n = 0;

        // 将未压缩数据读入字节数组
        while ((n = gzip.read(buffer)) >= 0) {
            out.write(buffer, 0, n);
        }
        // 使用指定的 charsetName，通过解码字节将缓冲区内容转换为字符串
        return out.toString("utf-8");
    }





}
