java实现生成二维码并压缩内容

        前景:由于公司需求一个工具,这个工具需要将csv文件中的数据存入二维码中,使用手机进行识别。

本文采用opencsv和google的zxing来将csv中的数据存储到二维码中,但是最终结果发现一个问题,明文存储在二维码中,将不能够存很多数据,因此,想了一个办法,便是使用GZIP对内容进行压缩后再存入二维码中。

一、目录结构

本文使用的是maven项目,bean目录存储需要将数据转换成的实体,util目录就是各个工具类,main目录主要是为了测试生成二维码并解压字符串。

java实现生成二维码并压缩内容_第1张图片

二、文件内容

        1.数据准备       

         这里准备了7条数据,包括姓名、性别、年龄。

java实现生成二维码并压缩内容_第2张图片

        2.pom依赖

        这里依赖包括,fastjson:用于将实体转换成json字符串,opencsv:读取csv文件所必需的,zxing:谷歌生成二维码的依赖,这里有一个坑:需要去集成lombok依赖,否则无法将读取的数据转换成对应实体的集合。


        
            com.alibaba
            fastjson
            1.2.76
        
        
        
            com.opencsv
            opencsv
            5.5.2
        

        
            org.projectlombok
            lombok
            1.18.12
        
        
        
            com.google.zxing
            core
            3.4.1
        

        
            com.google.zxing
            javase
            3.4.1
        

        3.People.class

        这里以人为例,人包括属性姓名、性别、年龄等,这里使用@CsvBindByName来与csv中的表格头部对应。

@Data
public class People {
    /**
     * 姓名
     */
    @CsvBindByName(column = "姓名")
    private String name;
    /**
     * 性别
     */
    @CsvBindByName(column = "性别")
    private String sex;
    /**
     * 年龄
     */
    @CsvBindByName(column = "年龄")
    private Integer age;
}

        4.OpencsvUtil.class

        这是读取csv文件的工具类,我将它封装成了一个泛型函数,其中fileName是文件名称路径(应该命名成filePath的,懒得改啦!!!),clazz就是需要将csv转换成所需实体。

/**
 * opencsv工具类
 */
public class OpencsvUtil {

    /**
     * 读取csv并转换成相应的bean
     *
     * @param fileName 文件名称路径
     * @param clazz    最终获取到的bean
     * @param       泛型
     */
    public static  List readCsvByNameToBean(String fileName, Class clazz) throws FileNotFoundException {
        // 定义流
        CsvToBean csvToBean = null;
        try {
            InputStreamReader in = new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8);
            HeaderColumnNameMappingStrategy mappingStrategy = new HeaderColumnNameMappingStrategy<>();
            // 设置bean类型
            mappingStrategy.setType(clazz);
            CsvToBeanBuilder build = new CsvToBeanBuilder(in);
            build.withMappingStrategy(mappingStrategy);
            // 设置分隔符
            build.withSeparator(CSVWriter.DEFAULT_SEPARATOR);
            csvToBean = build.build();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return csvToBean == null ? null : csvToBean.parse();
    }
}

        5.QRcodeUtil.class

        这个是生成二维码工具,可以根据需要手动设置二维码尺寸以及logo的宽度和高度。

/**
 * 二维码工具类
 */
public class QRcodeUtil {

    private static final String CHARSET = "utf-8";

    // 二维码尺寸
    private static final int QRCODE_SIZE = 500;

    // LOGO宽度
    private static final int LOGO_WIDTH = 128;

    // LOGO高度
    private static final int LOGO_HEIGHT = 29;

    /**
     * 创建二维码
     *
     * @param content 二维码的内容
     */
    public static BufferedImage createImage(String content) {
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = null;
        try {
            bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
                    hints);
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
                }
            }
            return image;
        } catch (WriterException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 插入LOGO
     *
     * @param source   二维码图片
     * @param logoPath LOGO图片地址
     */
    public static void insertImage(BufferedImage source, InputStream logoPath) {
        Image src = null;
        try {
            src = ImageIO.read(logoPath);
            // 插入LOGO
            Graphics2D graph = source.createGraphics();
            int x = (QRCODE_SIZE - LOGO_WIDTH) / 2;
            int y = (QRCODE_SIZE - LOGO_HEIGHT) / 2;
            graph.drawImage(src, x, y, LOGO_WIDTH, LOGO_HEIGHT, null);
            Shape shape = new RoundRectangle2D.Float(x, y, LOGO_WIDTH, LOGO_HEIGHT, 12, 12);
            graph.setStroke(new BasicStroke(3f));
            graph.draw(shape);
            graph.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

        6.ZipUtil.class

        由于二维码的存储内容有限,尤其是黑白二维码,存储的内容可以说是少之又少,因此可以使用GZIP对其进行压缩。

/**
 * 压缩工具
 */
public class ZipUtil {

    /**
     * 使用gzip压缩字符串
     *
     * @param str 要压缩的字符串
     */
    public static String compress(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = null;
        try {
            gzip = new GZIPOutputStream(out);
            gzip.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (gzip != null) {
                try {
                    gzip.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return new String(Base64.getEncoder().encode(out.toByteArray()));
    }

    /**
     * 使用gzip解压缩
     *
     * @param compressedStr 压缩字符串
     */
    public static String uncompress(String compressedStr) {
        if (compressedStr == null) {
            return null;
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = null;
        GZIPInputStream ginzip = null;
        byte[] compressed = null;
        String decompressed = null;
        try {
            compressed = Base64.getDecoder().decode(compressedStr);
            in = new ByteArrayInputStream(compressed);
            ginzip = new GZIPInputStream(in);
            byte[] buffer = new byte[1024];
            int offset = -1;
            while ((offset = ginzip.read(buffer)) != -1) {
                out.write(buffer, 0, offset);
            }
            decompressed = out.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ginzip != null) {
                try {
                    ginzip.close();
                } catch (IOException ignored) {
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ignored) {
                }
            }
            try {
                out.close();
            } catch (IOException ignored) {
            }
        }
        return decompressed;
    }
}

       7.TempFileUtil.class

        本文将二维码图片存储成临时文件,用户可以根据需求自行修改存储方式,在这里我定义了图片的后缀名,应该将后缀名作为一个参数传入的,这里懒得改啦!!!

/**
 * 临时文件工具类
 */
public class TempFileUtil {

    /**
     * 保存图片
     *
     * @param imageName     图片名称
     * @param bufferedImage 图片
     * @param imageType     图片类型
     */
    public static File createImageTempFile(String imageName, BufferedImage bufferedImage, String imageType) {
        try {
            File tempFile = File.createTempFile(imageName, ".png");
            // 将图片写入临时文件
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, imageType, baos);
            InputStream fis = new ByteArrayInputStream(baos.toByteArray());
            OutputStream fos = new FileOutputStream(tempFile);
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
            // 关闭流
            fis.close();
            fos.close();
            return tempFile;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

三、案例测试

        CreateQRcode.class

        本文将路径存储于“C:\\Users\\1\\Desktop\\data\\data.csv”,用户只需修改文件路径即可。文件所含内容请看第二章的第一节。

public class CreateQRcode {
    public static void main(String[] args) {
        String fileName = "C:\\Users\\1\\Desktop\\data\\data.csv";
        try {
            // 将csv数据转换成对应的bean并过滤
            List problemList = Objects.requireNonNull(OpencsvUtil.readCsvByNameToBean(fileName, People.class));
            //打印数据
            for (People people : problemList) {
                System.out.println(JSONObject.toJSONString(people));
            }
            // 将bean存入二维码
            String content = ZipUtil.compress(JSONObject.toJSONString(problemList));
            BufferedImage image = QRcodeUtil.createImage(content);
            if (image != null) {
                File png = TempFileUtil.createImageTempFile(new File(fileName).getName().split("\\.")[0], image, "png");
                assert png != null;
                System.out.println("存放路径:" + png.getAbsolutePath());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

        可见图片存放于:C:\Users\1\AppData\Local\Temp\data3809453543411187204.png

java实现生成二维码并压缩内容_第3张图片

        扫描二维码,可得识别结果:H4sIAAAAAAAAAIuuVkpMT1WyMrTQUSpOrVCyUno+ZbtSrQ5M2By7sAFM+OnSzUjCJBmCQ7EpitGxADCNnimhAAAA

        UnzipData.class

/**
 * @author anxin
 * @date 2022/4/2 21:53
 */
public class UnzipData {
    public static void main(String[] args) {
        String compressData = "H4sIAAAAAAAAAIuuVkpMT1WyMrTQUSpOrVCyUno+ZbtSrQ5M2By7sAFM+OnSzUjCJBmCQ7EpitGxADCNnimhAAAA";
        String uncompress = ZipUtil.uncompress(compressData);
        System.out.println("解压字符串成功!");
        System.out.println("---------------数据开始-------------");
        List people = JSONObject.parseArray(uncompress, People.class);
        for (People person : people) {
            System.out.println(JSONObject.toJSONString(person));
        }
        System.out.println("---------------数据结束-------------");
    }
}

        对扫描结果进行gzip解压缩,可得到二维码存入的内容,结果如下:

java实现生成二维码并压缩内容_第4张图片

你可能感兴趣的:(java小工具集合,java)