You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求实现持续扫描并自动保存的Java代码,改造二维码扫描逻辑

二维码持续自动扫描并保存的Java改造方案

核心改造思路

把原有的按钮触发单次扫描逻辑,改成后台循环扫描+自动保存的模式,核心要点包括:

  • 用循环替代单次触发,扫描成功后自动重启扫描
  • 加入线程安全的扫描状态控制,支持主动停止
  • 扫描异常不中断循环,保证稳定性
  • 扫描到内容后自动执行保存,无需人工干预

依赖准备(以Maven为例)

使用ZXing库处理二维码解码,先添加依赖:

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.5.2</version>
</dependency>

完整改造代码

以下代码实现了屏幕捕获式的持续扫描(如果是摄像头实时流,只需替换画面捕获部分),并自动保存二维码内容和截图:

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

public class QRCodeContinuousScanner {
    // 线程安全的扫描开关,用于启动/停止循环
    private final AtomicBoolean isScanning = new AtomicBoolean(true);
    // 扫描间隔(毫秒),降低CPU占用
    private static final int SCAN_INTERVAL = 1000;
    // 二维码文件保存根目录
    private static final String SAVE_DIR = "./scanned_qr_codes/";

    public static void main(String[] args) {
        QRCodeContinuousScanner scanner = new QRCodeContinuousScanner();
        // 初始化保存目录
        initSaveDir();
        // 启动扫描线程,避免阻塞UI或主线程
        new Thread(scanner::startContinuousScan).start();

        // 示例:模拟5秒后停止扫描(实际可通过按钮、外部事件触发)
        try {
            Thread.sleep(5000);
            scanner.stopScanning();
            System.out.println("扫描任务已停止");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    private static void initSaveDir() {
        File dir = new File(SAVE_DIR);
        if (!dir.exists() && !dir.mkdirs()) {
            System.err.println("无法创建二维码保存目录");
        }
    }

    public void startContinuousScan() {
        try (Robot robot = new Robot()) {
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            Rectangle captureArea = new Rectangle(screenSize);

            while (isScanning.get()) {
                // 捕获当前屏幕画面(如果是摄像头,替换为摄像头帧获取逻辑)
                BufferedImage screenCapture = robot.createScreenCapture(captureArea);
                String qrContent = decodeQRCode(screenCapture);

                if (qrContent != null && !qrContent.isBlank()) {
                    System.out.println("扫描到二维码:" + qrContent);
                    // 自动保存内容和截图
                    saveQRData(qrContent, screenCapture);
                    // 可选:停顿2秒避免重复扫描同一二维码
                    Thread.sleep(2000);
                }

                // 扫描间隔,减少资源消耗
                Thread.sleep(SCAN_INTERVAL);
            }
        } catch (AWTException | InterruptedException | IOException e) {
            System.err.println("扫描异常:" + e.getMessage());
        }
    }

    private String decodeQRCode(BufferedImage image) {
        try {
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result result = new QRCodeReader().decode(bitmap);
            return result.getText();
        } catch (NotFoundException | ChecksumException | FormatException ignored) {
            // 未识别到二维码,忽略异常继续循环
            return null;
        }
    }

    private void saveQRData(String content, BufferedImage image) throws IOException {
        String timestamp = String.valueOf(System.currentTimeMillis());
        // 保存二维码文本内容
        File contentFile = new File(SAVE_DIR + "qr_content_" + timestamp + ".txt");
        try (java.io.FileWriter writer = new java.io.FileWriter(contentFile)) {
            writer.write(content);
        }
        // 保存二维码截图
        File imageFile = new File(SAVE_DIR + "qr_image_" + timestamp + ".png");
        ImageIO.write(image, "PNG", imageFile);

        System.out.println("二维码数据已保存至:" + SAVE_DIR);
    }

    // 外部调用停止扫描的方法
    public void stopScanning() {
        isScanning.set(false);
    }
}

针对原有按钮触发代码的改造要点

如果你的原有代码是Swing/JavaFX的按钮触发逻辑,按以下步骤改造:

  1. 移除按钮点击事件的单次扫描逻辑:删除按钮ActionListener里的单次扫描、保存代码
  2. 封装扫描循环:把上述代码中的startContinuousScan方法整合到你的现有类中
  3. 添加扫描控制:新增一个"停止扫描"按钮,点击时调用stopScanning()方法
  4. 启动扫描:在程序初始化(比如init()方法)或"开始扫描"按钮点击时,启动扫描线程
  5. 线程隔离:扫描逻辑必须放在独立线程中,避免阻塞UI线程

内容的提问来源于stack exchange,提问作者shiela castro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 02:06:52