二维码初体验 com.google.zxing 实现

文章目录

  • 一、概述
  • 二、实现效果
    • 1. 完整版本
    • 2. 简化版本
  • 三、源码结构
  • 四、完整代码

一、概述

Java 操作二维码的开源项目很多,如 SwetakeQRCode、BarCode4j、Zxing 等,这边以Zxing 为例进行介绍。

二、实现效果

1. 完整版本

选择需要生成QR原始文件,支持 “清除空白行及空格” 以减少二维码图片大小。
二维码初体验 com.google.zxing 实现_第1张图片

2. 简化版本

支持输入文本内容,直接生成二维码
二维码初体验 com.google.zxing 实现_第2张图片

三、源码结构

代码结构
二维码初体验 com.google.zxing 实现_第3张图片
QrCodeUI: 完整版本代码
SimpleQrCodeUI:简化版本代码

四、完整代码

如何使用下面的备份文件恢复成原始的项目代码,请移步查阅:神奇代码恢复工具

icon.gificon.gif

//goto pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>file-to-qrcode</artifactId>
	<version>0.0.1</version>
	<name>file-to-qrcode</name>
	<url>http://maven.apache.org</url>
	<packaging>jar</packaging>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<log4j.version>2.12.1</log4j.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-slf4j-impl</artifactId>
			<version>${log4j.version}</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.12</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.6</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.5</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.7.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
//goto src\main\java\com\fly\MainRun.java
package com.fly;

import javax.swing.SwingUtilities;

import org.apache.commons.lang3.RandomUtils;

import com.fly.ui.QrCodeUI;
import com.fly.ui.SimpleQrCodeUI;

/**
 * 
 * MainRun
 * 
 * @author 00fly
 * @version [版本号, 2023年3月5日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class MainRun
{
    public static void main(String[] args)
    {
        // 随机运行
        boolean input = RandomUtils.nextBoolean();
        if (input)
        {
            SwingUtilities.invokeLater(() -> new QrCodeUI());
            return;
        }
        SwingUtilities.invokeLater(() -> new SimpleQrCodeUI());
        
    }
}
//goto src\main\java\com\fly\ui\QrCodeUI.java
package com.fly.ui;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import com.fly.utils.QRCodeUtil;

/*****
 * 界面操作展示类
 */
public class QrCodeUI extends JFrame
{
    private static final long serialVersionUID = -9154321945329564644L;
    
    // 界面组件
    JPanel panel = new JPanel();
    
    JTextArea textArea = new JTextArea();
    
    JTextField fileText = new JTextField(null, 40);
    
    JButton fileDirBrowse = new JButton("请选择");
    
    JButton removeButton = new JButton("清除空白行及空格");
    
    JButton qrButton = new JButton(" 生 成 二 维 码 ");
    
    JButton clearButton = new JButton(" 清 除 内 容 ");
    
    // 构造函数
    public QrCodeUI()
    {
        // 加载图标
        URL imgURL = getClass().getResource("/img/icon.gif");
        if (imgURL != null)
        {
            Image image = getToolkit().createImage(imgURL);
            setIconImage(image);
        }
        setTitle("二维码应用工具 V1.0");
        setSize(900, 550);
        Dimension screenSize = getToolkit().getScreenSize();
        Dimension frameSize = this.getSize();
        frameSize.height = Math.min(screenSize.height, frameSize.height);
        frameSize.width = Math.min(screenSize.width, frameSize.width);
        setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
        addMenu();
        addButton();
        try
        {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
        }
        catch (Exception e)
        {
        }
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        fileText.setFocusable(false);
    }
    
    // Menu set
    private void addMenu()
    {
        JMenuBar mb = new JMenuBar();
        // 一级菜单
        JMenu conf = new JMenu(" 系 统 ");
        // 子菜单
        JMenuItem exit = new JMenuItem("退出");
        exit.addActionListener(event -> System.exit(0));
        conf.add(exit);
        mb.add(conf);
        JMenu help = new JMenu(" 帮 助 ");
        JMenuItem about = new JMenuItem("关于工具");
        about.addActionListener((ActionEvent event) -> JOptionPane.showMessageDialog(null, "二维码应用工具 V1.0,00fly 于2023年3月。\n", "关于本工具", JOptionPane.INFORMATION_MESSAGE));
        help.add(about);
        mb.add(help);
        setJMenuBar(mb);
    }
    
    // JButton set
    private void addButton()
    {
        panel.setLayout(null);
        getContentPane().add(panel);
        
        JLabel textLabel = new JLabel("文件内容");
        textLabel.setBounds(20, 10, 120, 18);
        panel.add(textLabel);
        
        JLabel fileLabel = new JLabel(" 待生成QR原始文件");
        fileLabel.setBounds(30, 410, 240, 18);
        panel.add(fileLabel);
        
        textArea.setEditable(false);
        
        JScrollPane scroll = new JScrollPane(textArea);
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scroll.setBounds(20, 30, 850, 360);
        panel.add(scroll);
        
        fileText.setBounds(150, 410, 450, 24);
        fileText.setText(new File(" ").getAbsolutePath().trim());
        fileText.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等");
        panel.add(fileText);
        fileDirBrowse.setBounds(610, 410, 80, 25);
        fileDirBrowse.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等");
        fileDirBrowse.addActionListener(event -> {
            String path = fileText.getText();
            File xmlfile = new File(path);
            if (new File(fileText.getText()).exists())
            {
                xmlfile = new File(path).getParentFile();
            }
            JFileChooser fc = new JFileChooser(xmlfile);
            fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
            fc.setDialogTitle("原始文件选择");
            if (fc.showOpenDialog(null) == JFileChooser.CANCEL_OPTION)
            {
                return;
            }
            fc.setFileFilter(new FileFilter()
            {
                @Override
                public boolean accept(File file)
                {
                    String name = file.getName().toLowerCase();
                    return name.endsWith(".xml") || name.endsWith(".java") || name.endsWith(".yml") || name.endsWith(".yaml") || name.endsWith(".md") || name.endsWith(".txt");
                }
                
                @Override
                public String getDescription()
                {
                    return "";
                }
            });
            File f = fc.getSelectedFile();
            if (f != null && f.isFile())
            {
                fileText.setText(f.getAbsolutePath());
                try
                {
                    textArea.setText(FileUtils.readFileToString(f, StandardCharsets.UTF_8));
                    qrButton.setEnabled(true);
                }
                catch (IOException e)
                {
                }
            }
        });
        panel.add(fileDirBrowse);
        
        removeButton.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                String content = textArea.getText();
                if (StringUtils.isNotBlank(content))
                {
                    content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");
                    textArea.setText(content);
                }
            }
        });
        removeButton.setBounds(100, 450, 160, 30);
        removeButton.add(qrButton);
        panel.add(removeButton);
        
        qrButton.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if (!qrButton.isEnabled())
                {
                    return;
                }
                try
                {
                    String content = textArea.getText();
                    BufferedImage image = QRCodeUtil.createImage(content, "", false);
                    new ShowDialog(image);
                }
                catch (Exception e1)
                {
                    JOptionPane.showMessageDialog(null, "失败原因: " + e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        qrButton.setBounds(350, 450, 160, 30);
        qrButton.setEnabled(false);
        panel.add(qrButton);
        
        clearButton.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                textArea.setText(null);
                qrButton.setEnabled(false);
            }
        });
        clearButton.setBounds(600, 450, 160, 30);
        panel.add(clearButton);
    }
    
    // Run
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> new QrCodeUI());
    }
}
//goto src\main\java\com\fly\ui\ShowDialog.java
package com.fly.ui;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;

/**
 * 
 * qr显示弹出窗口
 * 
 * @author 00fly
 * @version [版本号, 2023年3月3日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ShowDialog extends JDialog
{
    private static final long serialVersionUID = 8010838747205419843L;
    
    public ShowDialog(BufferedImage image)
    {
        super();
        // 加载图标
        URL imgURL = getClass().getResource("/img/icon.gif");
        if (imgURL != null)
        {
            setIconImage(getToolkit().createImage(imgURL));
        }
        setTitle("请扫描二维码");
        setSize(510, 530);
        
        // 自适应居中处理
        Dimension screenSize = getToolkit().getScreenSize();
        Dimension dialogSize = getSize();
        dialogSize.height = Math.min(screenSize.height, dialogSize.height);
        dialogSize.width = Math.min(screenSize.width, dialogSize.width);
        setLocation((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2);
        
        // 生成二维码图片
        add(new JLabel(new ImageIcon(image)));
        
        setVisible(true);
        setResizable(false);
        setAlwaysOnTop(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }
}
//goto src\main\java\com\fly\ui\SimpleQrCodeUI.java
package com.fly.ui;

import java.awt.BorderLayout;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.apache.commons.lang3.StringUtils;

import com.fly.utils.QRCodeUtil;

/**
 * 
 * 文本二维码生成简化版本
 * 
 * @author 00fly
 * @version [版本号, 2023年3月3日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class SimpleQrCodeUI extends JFrame
{
    private static final long serialVersionUID = -708209618541039567L;
    
    JTextArea textArea = new JTextArea();
    
    JButton qrButton = new JButton("生 成 二 维 码");
    
    public SimpleQrCodeUI()
        throws HeadlessException
    {
        initComponent();
        
        // 设定用户界面的外观
        try
        {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
        }
        catch (Exception e)
        {
        }
        
        // 加载图标
        URL imgURL = getClass().getResource("/img/icon.gif");
        if (imgURL != null)
        {
            Image image = getToolkit().createImage(imgURL);
            setIconImage(image);
        }
        this.setTitle("二维码应用工具 V1.0");
        this.setBounds(400, 200, 1200, 550);
        this.setResizable(true);
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    /**
     * 组件初始化
     * 
     * @see [类、类#方法、类#成员]
     */
    private void initComponent()
    {
        textArea.setToolTipText("输入需要生成二维码图片的原始文本内容");
        
        // JTextArea不自带滚动条,因此就需要把文本区放到一个滚动窗格中
        JScrollPane scroll = new JScrollPane(textArea);
        scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        
        this.add(scroll, BorderLayout.CENTER);
        this.add(qrButton, BorderLayout.SOUTH);
        qrButton.addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                try
                {
                    String content = textArea.getText();
                    if (StringUtils.isNotBlank(content))
                    {
                        content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");
                        BufferedImage image = QRCodeUtil.createImage(content, "", false);
                        new ShowDialog(image);
                    }
                }
                catch (Exception e1)
                {
                    JOptionPane.showMessageDialog(null, e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
    }
    
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> new SimpleQrCodeUI());
    }
}
//goto src\main\java\com\fly\utils\BufferedImageLuminanceSource.java
package com.fly.utils;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

import com.google.zxing.LuminanceSource;

public class BufferedImageLuminanceSource extends LuminanceSource
{
    private final BufferedImage image;
    
    private final int left;
    
    private final int top;
    
    public BufferedImageLuminanceSource(BufferedImage image)
    {
        this(image, 0, 0, image.getWidth(), image.getHeight());
    }
    
    public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height)
    {
        super(width, height);
        
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        if (left + width > sourceWidth || top + height > sourceHeight)
        {
            throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
        }
        
        for (int y = top; y < top + height; y++)
        {
            for (int x = left; x < left + width; x++)
            {
                if ((image.getRGB(x, y) & 0xFF000000) == 0)
                {
                    image.setRGB(x, y, 0xFFFFFFFF); // = white
                }
            }
        }
        
        this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
        this.image.getGraphics().drawImage(image, 0, 0, null);
        this.left = left;
        this.top = top;
    }
    
    @Override
    public byte[] getRow(int y, byte[] row)
    {
        if (y < 0 || y >= getHeight())
        {
            throw new IllegalArgumentException("Requested row is outside the image: " + y);
        }
        int width = getWidth();
        if (row == null || row.length < width)
        {
            row = new byte[width];
        }
        image.getRaster().getDataElements(left, top + y, width, 1, row);
        return row;
    }
    
    @Override
    public byte[] getMatrix()
    {
        int width = getWidth();
        int height = getHeight();
        int area = width * height;
        byte[] matrix = new byte[area];
        image.getRaster().getDataElements(left, top, width, height, matrix);
        return matrix;
    }
    
    @Override
    public boolean isCropSupported()
    {
        return true;
    }
    
    @Override
    public LuminanceSource crop(int left, int top, int width, int height)
    {
        return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
    }
    
    @Override
    public boolean isRotateSupported()
    {
        return true;
    }
    
    @Override
    public LuminanceSource rotateCounterClockwise()
    {
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
        BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g = rotatedImage.createGraphics();
        g.drawImage(image, transform, null);
        g.dispose();
        int width = getWidth();
        return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
    }
}
//goto src\main\java\com\fly\utils\QRCodeUtil.java
package com.fly.utils;

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRCodeUtil
{
    private static final String FORMAT_NAME = "JPG";
    
    // 二维码尺寸
    private static final int QRCODE_SIZE = 500;
    
    // LOGO宽度
    private static final int WIDTH = 60;
    
    // LOGO高度
    private static final int HEIGHT = 60;
    
    public static BufferedImage createImage(String content, String imgPath, boolean needCompress)
        throws Exception
    {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix 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_RGB);
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        if (imgPath == null || "".equals(imgPath))
        {
            return image;
        }
        // 插入图片
        insertImage(image, imgPath, needCompress);
        return image;
    }
    
    private static void insertImage(BufferedImage source, String imgPath, boolean needCompress)
        throws Exception
    {
        File file = new File(imgPath);
        if (!file.exists())
        {
            System.err.println(imgPath + " 该文件不存在!");
            return;
        }
        Image src = ImageIO.read(new File(imgPath));
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress)
        {
            // 压缩LOGO
            width = Math.min(width, WIDTH);
            height = Math.min(height, HEIGHT);
            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
        }
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }
    
    public static void encode(String content, String imgPath, String destPath, boolean needCompress)
        throws Exception
    {
        BufferedImage image = createImage(content, imgPath, needCompress);
        mkdirs(destPath);
        ImageIO.write(image, FORMAT_NAME, new File(destPath));
    }
    
    public static BufferedImage encode(String content, String imgPath, boolean needCompress)
        throws Exception
    {
        BufferedImage image = createImage(content, imgPath, needCompress);
        return image;
    }
    
    public static void mkdirs(String destPath)
    {
        File file = new File(destPath);
        if (!file.exists() && !file.isDirectory())
        {
            file.mkdirs();
        }
    }
    
    public static void encode(String content, String imgPath, String destPath)
        throws Exception
    {
        encode(content, imgPath, destPath, false);
    }
    
    public static void encode(String content, String destPath)
        throws Exception
    {
        encode(content, null, destPath, false);
    }
    
    public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
        throws Exception
    {
        BufferedImage image = createImage(content, imgPath, needCompress);
        ImageIO.write(image, FORMAT_NAME, output);
    }
    
    public static void encode(String content, OutputStream output)
        throws Exception
    {
        encode(content, null, output, false);
    }
    
    public static String decode(File file)
        throws Exception
    {
        BufferedImage image = ImageIO.read(file);
        if (image == null)
        {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Hashtable<DecodeHintType, String> hints = new Hashtable<>();
        hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }
    
    public static String decode(String path)
        throws Exception
    {
        return decode(new File(path));
    }
}
//goto src\main\resources\log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="off" monitorInterval="0">
	<!-- 常量引用 -->
	<properties>
		<property name="LOG_HOME">logs</property>
		<property name="PROJECT">qrcode</property>
		<property name="FORMAT">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property>
	</properties>

	<!-- appender用于接收各种日志 -->
	<appenders>
		<!-- 常见的输出到console,常用于开发环境中,默认是system_err,还有一个system_out -->
		<console name="Console" target="system_out">
			<!-- appender级别的日志过滤 -->
			<!-- <thresholdFilter level="info" onMatch="accept" onMismatch="deny"/> -->
			<patternLayout pattern="${FORMAT}" />
		</console>

		<RollingRandomAccessFile name="RollingFileInfo" fileName="${LOG_HOME}/${PROJECT}/info.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
			<Filters>
				<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral" />
				<ThresholdFilter level="warn" onMatch="deny" onMismatch="neutral" />
				<ThresholdFilter level="info" onMatch="accept" onMismatch="deny" />
			</Filters>
			<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
			<Policies>
				<TimeBasedTriggeringPolicy modulate="true" interval="1" />
				<SizeBasedTriggeringPolicy size="20 MB" />
			</Policies>

			<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件 -->
			<DefaultRolloverStrategy max="20">
				<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
					<IfFileName glob="*/info-*.log.gz" />
					<IfLastModified age="60d" />
				</Delete>
			</DefaultRolloverStrategy>
		</RollingRandomAccessFile>

		<RollingRandomAccessFile name="RollingFileWarn" fileName="${LOG_HOME}/${PROJECT}/warn.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
			<Filters>
				<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral" />
				<ThresholdFilter level="warn" onMatch="accept" onMismatch="deny" />
			</Filters>
			<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
			<Policies>
				<TimeBasedTriggeringPolicy modulate="true" interval="1" />
				<SizeBasedTriggeringPolicy size="20 MB" />
			</Policies>
			<DefaultRolloverStrategy max="20">
				<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
					<IfFileName glob="*/warn-*.log.gz" />
					<IfLastModified age="60d" />
				</Delete>
			</DefaultRolloverStrategy>
		</RollingRandomAccessFile>

		<RollingRandomAccessFile name="RollingFileError" fileName="${LOG_HOME}/${PROJECT}/error.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
			<ThresholdFilter level="error" onMatch="accept" onMismatch="deny" />
			<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
			<Policies>
				<TimeBasedTriggeringPolicy modulate="true" interval="1" />
				<SizeBasedTriggeringPolicy size="20 MB" />
			</Policies>
			<DefaultRolloverStrategy max="20">
				<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
					<IfFileName glob="*/error-*.log.gz" />
					<IfLastModified age="60d" />
				</Delete>
			</DefaultRolloverStrategy>
		</RollingRandomAccessFile>
	</appenders>

	<!-- 接收appender -->
	<loggers>
		<!-- Spring -->
		<logger name="org.springframework" level="INFO" />

		<!-- root logger,一般用于放置所有的appender -->
		<root level="INFO">
			<appender-ref ref="Console" />
			<appender-ref ref="RollingFileInfo" />
			<appender-ref ref="RollingFileWarn" />
			<appender-ref ref="RollingFileError" />
		</root>
	</loggers>
</configuration>


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

你可能感兴趣的:(Java,雕虫小技,java,二维码)