java压缩字符串并生成二维码

2023-11-17

针对特殊需求需要使用二维码传输数据,为了降低二维码的复杂度和提高数据传输量,需要先对数据进行压缩,然后生成二维码。压缩后的数据是byte[],如果再转回字符串会严重影响压缩效果,因此考虑直接使用byte[]生成和解析二维码。为了实现使用byte[]生成二维码,对zxing的core-3.4.0进行了改写。

改写步骤:zxing使用byte数组生成二维码和解析二维码
改写的jar:重新编译的可使用byte[]生成二维码的zxing-core-3.4.0

使用时需要导入改写的core-3.4.0.jar和javase-3.4.0.jar。压缩使用jdk8自带的GZIP对字符串进行压缩,测试了几次压缩率大约在50%~60%之间,测试的次数不多可能不是太准确。详细代码如下,具体使用参照main方法。

    private static final Charset UTF8 = Charset.forName("UTF-8");//编码格式
    private static final int MARGIN = 10;//二维码边距
	private static final int WIDTH = 800;//二维码宽
	private static final int HEIGHT = 800;//二维码高
	private static final String SUFFIX = "jpg";//图片后缀名
	private static final String QRPATH = "/qrcode.jpg";//二维码生成路径
    /**
	 * 压缩字符串为数组
	 * @param str
	 * @return
	 */
	public static byte[] compress(String str) {
	    if (str == null || str.length() == 0) {
	        return null;
	    }
	    ByteArrayOutputStream out= new ByteArrayOutputStream();
	    try (GZIPOutputStream gzip = new GZIPOutputStream(out);){
	        gzip.write(str.getBytes(UTF8));
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	    return out.toByteArray();
	}
	/**
	 * 数组解压缩为字符串
	 * @param bytes
	 * @return
	 */
	public static String uncompress(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        try (GZIPInputStream gzip = new GZIPInputStream(in);){
            byte[] buffer = new byte[1024];
            int n;
            while ((n = gzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
        } catch (IOException e) {
        	e.printStackTrace();
        }
        return new String(out.toByteArray(),SysUtils.UTF8);
    }
	/**
	 *指定位置生成二维码
	 * @param data 二维码数据
	 * @return
	 */
	public static String encodeQRCode(byte[] data) {
		File file = new File(QRPATH);
		encodeQRCode(data, ErrorCorrectionLevel.M, MARGIN, WIDTH, HEIGHT, SUFFIX, file.toPath());
		return QRPATH;
	}
	/**
	 * 生成二维码
	 * @param data 二维码数据
	 * @param level 纠错等级
	 * @param margin 二维码边距
	 * @param width 二维码宽
	 * @param height 二维码高
	 * @param suffix 二维码图片后缀名
	 * @param path 二维码图片路径
	 */
	public static void encodeQRCode(byte[] data, ErrorCorrectionLevel level, int margin, int width, int height, String suffix, Path path) {
		// 定义二维码的参数
        HashMap<EncodeHintType, Object> hashMap = new HashMap<EncodeHintType, Object>();
        // 设置二维码纠错等级
        hashMap.put(EncodeHintType.ERROR_CORRECTION, level);
        // 设置二维码边距
        hashMap.put(EncodeHintType.MARGIN, margin);
        try {
            // 开始生成二维码
            BitMatrix bitMatrix = new MultiFormatWriter().encodeQRCode(data, width, height, hashMap);
            // 导出到指定目录
            MatrixToImageWriter.writeToPath(bitMatrix, suffix, path);
        }  catch (Exception e) {
            e.printStackTrace();
        }
	}
	/**
	 * 识别二维码
	 * @param file
	 * @return
	 */
	public static Result decodeQRCode(File file) {
		try {
			return decodeQRCode(ImageIO.read(file));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 识别二维码
	 * @param image
	 * @return
	 */
	public static Result decodeQRCode(BufferedImage image) {
		LuminanceSource source = new BufferedImageLuminanceSource(image);
	    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
	    Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
	    hints.put(DecodeHintType.CHARACTER_SET, UTF8);
	    try {
	        return new MultiFormatReader().decodeQRCode(bitmap, hints);
	    } catch (NotFoundException e) {
	        e.printStackTrace();
	    }
	    return null;
	}
	public static void main(String...strings) {
		String data = "针对特殊需求需要使用二维码传输数据,为了降低二维码的复杂度和提高数据传输量,需要先对数据进行压缩,然后生成二维码。压缩后的数据是byte[],如果再转回字符串会严重影响压缩效果,因此考虑直接使用byte[]生成和解析二维码。为了实现使用byte[]生成二维码,对zxing的core-3.4.0进行了改写";
		encodeQRCode(compress(data));
		System.out.println(uncompress(decodeQRCode(new File(QRPATH)).getRawBytes()));
	}

compress(String str):压缩字符串为byte数组,编码格式为UTF-8,可根据需要修改配置。
uncompress(byte[] bytes):解压缩byte数组为字符串,编码格式为UTF-8,可根据需要修改配置。
encodeQRCode(byte[] data):使用byte数组生成二维码,可根据需要修改宽、高等配置。
encodeQRCode(byte[] data, ErrorCorrectionLevel level, int margin, int width, int height, String suffix, Path path) :使用byte数组生成二维码,可自定义二维码宽、高、纠错等级等。
decodeQRCode(File file):识别二维码图片,解析二维码得到Result对象,使用Result对象的getText()方法得到字符串,压缩字符串生成的二维码不可使用,应使用getRawBytes()方法得到byte数组进行解压缩。
decodeQRCode(BufferedImage image):同decodeQRCode(File file),但是可以扩展解析base64二维图片,代码如下:

	/**
	 * 识别二维码
	 * @param base64Img
	 * @return
	 */
	public static Result decodeQRCode(String base64Img) {
		if(base64Img.startsWith("data:image")) {
			base64Img = base64Img.split(",")[1];
			byte[] buf = Base64.getDecoder().decode(base64Img);
			InputStream input = new ByteArrayInputStream(buf);
			BufferedImage image;
			try {
				image = ImageIO.read(input);
				return decodeQRCode(image);
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
		return null;
	}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java压缩字符串并生成二维码 的相关文章

随机推荐