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压缩字符串并生成二维码 的相关文章

  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • 如何测试调用父类的受保护(不需要的)方法的方法?

    我陷入了一个非常奇怪的情况 我有一些需要测试的特定代码 这里是 public class A The real method of real class is so big that I just don t want to test it
  • 如何识别 Java 中的不可变对象

    在我的代码中 我正在创建一个对象集合 这些对象将由各种线程以只有在对象不可变的情况下才安全的方式访问 当尝试将新对象插入到我的集合中时 我想测试它是否是不可变的 如果不是 我将抛出异常 我能做的一件事是检查一些众所周知的不可变类型 priv
  • 在 Hibernate 中创建 UPDATE RETURNING 查询

    在 Oracle 中 我们可以创建一个更新查询 该查询将使用 RETURNING 子句返回更新的记录 Hibernate中有类似的功能吗 除了数据库生成的值之外 Hibernate 显然不需要返回更新的实例 因为对象传递给Session s
  • 是否可以从另一个方法传递 args[] 来调用 main 方法?

    我试图从另一个传递参数的方法调用类的主要方法 就像从命令行运行该类时一样 有没有办法做到这一点 您可以致电main方法就像您调用任何其他 静态 方法一样 MyClass main new String arg1 arg2 arg3 Exam
  • 正确使用 JDBC 连接池 (Glassfish)

    我需要在 Java Web 服务中作为会话 bean 实现数据库连接 但我不确定我这样做是否正确 我创建了一个类 public final class SQLUtils private static DataSource m ds null
  • 用 java 编写解释器时的 switch 或 if 语句

    当前的作业需要我编写一个程序 以一种非常微小且基本的编程语言 行为有点像 FORTRAN 来读取包含指令的文件并执行这些指令 基本上它是我猜的语言的简单解释器 它是完全线性的 所有语句都是按顺序定义的 并且只有字符串和整数变量 我需要查找和
  • 如何将自定义日志处理程序添加到 Google App Engine?

    我正在尝试向我的 java 应用程序添加自定义日志处理程序 我已经实现了一个扩展 java util Logging Handler 类的 InnerLogger 类 在我的logging properties中声明为处理程序 handle
  • 以编程方式设置 Logback Appender 路径

    我正在尝试以编程方式设置 Logback 附加程序路径 滚动文件附加器 http logback qos ch apidocs ch qos logback core rolling RollingFileAppender html准确地说
  • 从关卡堆栈中获取相对比例的数学

    为这个可怕的标题道歉 我花了 10 分钟试图用一句话来解释这一点 但失败了 虽然提示这个问题的应用程序是用Java Android 编写的 但我认为它非常通用并且适用于任何语言 欢迎使用伪代码 或简单的英语 回复 我不确定是否应该标记所有通
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • 从 sbt 程序集运行 uber jar 会导致错误:无法找到或加载主类

    我有一个使用 sbt 程序集插件打包为 uber jar 的 Spark 作业 这build sbt指定一个可运行的 main 作为生成的 uber jar 的目标 mainClass in assembly Some com foo Ba
  • 打印 jasper 文件时执行报表 SQL 语句时出错

    我修改了一个旧项目 但无法确定这段代码有什么问题 使用下面的 jrxml它创造 jasper文件 当我打印 jasper 文件时 使用此代码JasperPrint jasperPrint JasperFillManager fillRepo
  • 在 eclipse 之外将 Spring MVC 应用程序部署到 tomcat 的幕后会发生什么?

    我猜想使用像 eclipse 这样很棒的 IDE 的一个缺点是你会忽略应用程序幕后发生的事情 我是一名 Ruby 开发人员 所以不是一名 Java 老手 所以我一直在用 java 编写一个项目 并使用 spring 框架进行 IOC 和 M
  • 如何通过子 POJO 的属性过滤复合 ManyToMany POJO?

    我有两个像这样的房间实体 Entity public class Teacher implements Serializable PrimaryKey autoGenerate true public int id ColumnInfo n
  • 为什么现在()? (客观化)

    为什么我想要异步加载 Objectify 实体 异步加载到底意味着什么 根据客观化有关加载的文档 https code google com p objectify appengine wiki BasicOperations Loadin
  • 找不到符号assertEquals

    我正在尝试为计算器编写第一个单元测试 但 NetBeans 说它找不到该符号assertEquals和注释 Test 我应该包括一些东西吗 我正在使用 NetBeans 7 3 1 和 W7 package calculator impor
  • 从命令行运行 Maven 插件的语法是什么。

    我看到这里已经有人问过这个问题 如何从命令行执行maven插件 https stackoverflow com questions 12930656 how to execute maven plugin from command line
  • 使用 Runtime.getRuntime().exec() 进行重定向不起作用

    我需要从程序执行命令 命令行是可以的 我在终端试了一下 但是在程序中不行 我从我的代码中添加一个副本 File dir new File videos String children dir list if children null Ei
  • Integer.parseInt 引发的 NumberFormatException

    嘿 我在学校上编码课 但老师没有很好地解释 所以我们必须在网上查找我所做的信息 但我无法找到代码中的错误 你能帮我吗 char end s do System out println Tipo de boleto char boleto c

随机推荐