浅浅的总结下zxing生成条形码、二维码

二维码
placeholder image
admin 发布于:2014-06-06 23:18:00
阅读:loading

 就摸索了一天而已,掌握的还很少,这里浅浅的整理一下关于这块知识吧,也算是对这块技术的总结吧,有说到不正确的地方求绕了吧。此为背景。
       现在这个项目里面用到了条形码,关于此技术点很早很早都有了解了,当然了解的程度为有java组件、jQuery插件都可以实现,仅此而已。在open-open的经验库里面看到的条形码最多的就是barcode4j这个组件了,但很快又发现了zxing组件,看介绍说此组件不仅能够实现条形码还能实现二维码,不觉中觉得这个更好。下面总结一下今天关于这两个组件的了解吧。
        都是开源的,先说下barcode4j吧,最后项目中还是没有用这个组件,秉着要做就做到个人认为是最好的程度吧,下载地址为
http://sourceforge.net/projects/barcode4j/ 下载下来的组件包包括example目录,里面的例子我基本没找到运行的,在build目录下找到了一个barcode4j.war,试了下这个例子没正常运行起来,无缘更加深入了解一点吧。不过查看了下web.xml里面的配置找到了一个servlet的几个mapping,手动敲地址也能看得到效果。默认值为0-9,可以传递msg来改变默认值。运行效果如下:

image.png

image.png

仅此再没多点的了解了,重点说下zxing组件吧。 
       
       了解了一下,zxing出自于google的开源项目,下载地址为:https://github.com/zxing/zxing/ 完整的zip包有120M,里面有关于好几种语言的调用方式,我所关注的也就是core和javase而已,少废话,直接导入已经存在的maven工程core和javase,其实这些工程之间的关系是一个核心是程序实现,另外一些工程是其配备其他语言的实现客户端,导入后的截图为:

image.png

看下他的ZXing Java SE extensions 程序吧,有两个文件是可以直接运行的示例文件,可以先运行这两个例子先来个入门级体验,详细看图:

image.png

 对于这两个类稍稍说明一下,CommandLineRunner.java示例需要添加main函数运行的参数,至于怎么添加略过;GUIRunner.java示例则是swing窗口,需要添加一个条形码或者二维码的图片文件可以看到运行结果。

       同时java的实现,我们直接把javase client的代码拷贝至core中,再重新打成一个jar文件,这样再添加到项目使用时只需要添加一个jar包就可以了,在用maven打包的时候,发现这个工程打包需要好几分钟,果断流弊的人写出的程序瞬间觉得太流弊了。打包完成之后将
%REPOSITORY_HOME%\com\google\zxing\core\3.1.1-SNAPSHOT目录中的core-3.1.1-SNAPSHOT.jar文件拷贝到自己的工程当中,也截个图吧,此图为内涵图,将图片保存到本地,使用360压缩方式打开就能看到我打成的3个jar包,如下图:

image.png

代码工程里面的程序,写了两个类,一个是针对于客户端实现的封装类,一个是生成条形码的servlet类,分别为:
Util代码: 

package com.camelot.eps.common.util;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import java.io.OutputStream;

import java.nio.file.Path;

import java.util.HashMap;

import java.util.Map;

import com.google.zxing.BarcodeFormat;

import com.google.zxing.BinaryBitmap;

import com.google.zxing.EncodeHintType;

import com.google.zxing.LuminanceSource;

import com.google.zxing.MultiFormatReader;

import com.google.zxing.MultiFormatWriter;

import com.google.zxing.ReaderException;

import com.google.zxing.Result;

import com.google.zxing.WriterException;

import com.google.zxing.client.j2se.BufferedImageLuminanceSource;

import com.google.zxing.client.j2se.ImageReader;

import com.google.zxing.client.j2se.MatrixToImageWriter;

import com.google.zxing.common.BitMatrix;

import com.google.zxing.common.HybridBinarizer;

public class BarCodeUtil {

    /**

     * <pre>

     * 对已存在的文件地址进行解码,Copy to 下载的源码中的例子

     * </pre>

     * 

     * @param file

     *            文件路径

     * @return 解码后的字符串

     * @author chendd, 2014-6-6 上午11:03:01

     */

    private static String getDecodeText(Path file) {

        BufferedImage image;

        try {

            image = ImageReader.readImage(file.toUri());

        } catch (IOException ioe) {

            return ioe.toString();

        }

        LuminanceSource source = new BufferedImageLuminanceSource(image);

        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        Result result;

        try {

            result = new MultiFormatReader().decode(bitmap);

        } catch (ReaderException re) {

            re.printStackTrace();

            return re.toString();

        }

        return String.valueOf(result.getText());

    }

    /**

     * <pre>

     * 根据文件路径和类型(条形码/二维码等)写入相关文件

     * </pre>

     * 

     * @param contents

     *            写入类型

     * @param type

     *            写入的图片类型,如二维码、条形码等等

     * @param format

     *            图片格式

     * @param width

     *            图片宽度

     * @param height

     *            图片高度

     * @param writeFile

     *            写入文件

     * @throws Exception

     *             抛出异常的爱

     * @author chendd, 2014-6-6 下午3:50:39

     */

    public static void writeToPath(String contents, BarcodeFormat type,

            String format, int width, int height, File writeFile)

            throws Exception {

        BitMatrix matrix = new MultiFormatWriter().encode(contents, type,

                width, height);

        MatrixToImageWriter.writeToPath(matrix, format, writeFile.toPath());

    }

    public static void writeToStream(String contents, BarcodeFormat type,

            String format, int width, int height, OutputStream os)

            throws Exception {

        BitMatrix matrix = new MultiFormatWriter().encode(contents, type,

                width, height);

        MatrixToImageWriter.writeToStream(matrix, format, os);

    }

    public static void writeToStream(String contents, OutputStream os)

            throws WriterException, IOException {

        BitMatrix matrix = new MultiFormatWriter().encode(contents,

                BarcodeFormat.CODE_128, 385, 190);

        MatrixToImageWriter.writeToStream(matrix, "png", os);

    }

    // CODE_128

    // PDF_417能够适用,只是长相不一样,

    public static void main(String[] args) throws Exception {

        String contents = "T1042014060516990012";

        System.out.println(contents.length());

        // 写入二维码

        Map<EncodeHintType, Object> maps = new HashMap<>();

        maps.put(EncodeHintType.CHARACTER_SET, "utf-8");

        BitMatrix matrix = new MultiFormatWriter().encode(contents,

                BarcodeFormat.QR_CODE, 385, 190, maps);

        MatrixToImageWriter.writeToPath(matrix, "png"new File(

                "f:\\tt\\11.png").toPath());

        System.out.println("文件生成成功...");

        // 读取二维码文件

        String content = getDecodeText(new File("f:\\tt\\11.png").toPath());

        System.out.println("解析文件内容为:" + content);

    }

}

 说明:此utils类包括了一个根据编码文件进行解码的实现,拷贝与官网提供的例子实现,另对输出图片的几个函数进行了简单封装。

 Servlet代码:

package com.camelot.eps.common.servlets;

import java.io.IOException;

import java.io.OutputStream;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.camelot.eps.common.util.BarCodeUtil;

import com.google.zxing.BarcodeFormat;

public class BarCodeServlet extends HttpServlet {

    /**

     * 

     */

    private static final long serialVersionUID = 1L;

    private ServletConfig config;

    @Override

    public void init(ServletConfig config) throws ServletException {

        this.config = config;

    }

    @Override

    protected void doGet(HttpServletRequest request,

            HttpServletResponse response) throws ServletException, IOException {

        String content = request.getParameter("content");// 获取要写入的内容

        if (StringUtils.isEmpty(content)) {

            // 处理为空的情况

        }

        OutputStream os = response.getOutputStream();

        String width = request.getParameter("width");// 获取宽度,如果没有则使用默认值

        if (StringUtils.isEmpty(width)) {

            width = config.getInitParameter("width");

        }

        String height = request.getParameter("height");// 获取高度,如果没有则使用默认值

        if (StringUtils.isEmpty(height)) {

            height = config.getInitParameter("height");

        }

        String imageType = config.getInitParameter("imageType");// 获取系统配置的图片类型

        String type = request.getParameter("type");// 获取系统配置使用的条形码类型

        if (StringUtils.isEmpty(type)) {

            type = config.getInitParameter("type");

        }

        try {

            BarCodeUtil.writeToStream(content, BarcodeFormat.valueOf(type),

                    imageType, Integer.parseInt(width),

                    Integer.parseInt(height), os);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    @Override

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)

            throws ServletException, IOException {

        this.doGet(req, resp);

    }

    @Override

    public void destroy() {

        this.config = null;

    }

}

 

  web.xml代码

<!-- 添加条形码Servlet -->

  <servlet>

      <servlet-name>barCode</servlet-name>

    <servlet-class>com.camelot.eps.common.servlets.BarCodeServlet</servlet-class>

    <init-param>

        <description>生成的条形码默认宽度,页面上需要更改可传递第参数名来覆盖</description>

        <param-name>width</param-name>

        <param-value>180</param-value>

    </init-param>

    <init-param>

        <description>生成的条形码默认高度,页面上需要更改可传递参数名来覆盖</description>

        <param-name>height</param-name>

        <param-value>70</param-value>

    </init-param>

    <init-param>

        <description>配置使用生成的图片格式</description>

        <param-name>imageType</param-name>

        <param-value>png</param-value>

    </init-param>

    <init-param>

        <description>生成的条形码类型,可以是条形码也可以是二维码等等其他类型</description>

        <param-name>type</param-name>

        <param-value>CODE_128</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>barCode</servlet-name>

    <url-pattern>/createBarCode</url-pattern>

  </servlet-mapping>

        Servlet里面的BarcodeFormat.valueOf(type)这个代码很给力,BarcodeFormat类继承于Enum类,我们可以根据配置或传递类型来实现代码不更改就可以实现图形的类型,当然这取决于这个type之外,也跟传递的content内容有关。关于它的类型看下面这个图吧:

image.png

运行效果:


@20150828近期对于此功能做了一个线上版本的演示功能(如今新版博客已下线)

参考地址为:http://chendd.cn/demo/qrCode/index.jsp

image.png

 点赞


 发表评论

当前回复:作者

 评论列表


留言区