Java 基于zxing的QR码编解码

Java 基于zxing的QR码编解码,java,barcode,qr-code,zxing,Java,Barcode,Qr Code,Zxing,好的,所以我要放弃这个机会,这里有人以前用过zxing。我正在开发一个Java应用程序,它需要做的一件事是将一个字节数组的数据编码成QR码,然后在以后对其进行解码 下面是我的编码器的示例: byte[] b = {0x48, 0x45, 0x4C, 0x4C, 0x4F}; //convert the byte array into a UTF-8 string String data; try { data = new String(b, "UTF8"); } catch (Unsup

好的,所以我要放弃这个机会,这里有人以前用过zxing。我正在开发一个Java应用程序,它需要做的一件事是将一个字节数组的数据编码成QR码,然后在以后对其进行解码

下面是我的编码器的示例:

byte[] b = {0x48, 0x45, 0x4C, 0x4C, 0x4F};
//convert the byte array into a UTF-8 string
String data;
try {
    data = new String(b, "UTF8");
}
catch (UnsupportedEncodingException e) {
 //the program shouldn't be able to get here
 return;
}

//get a byte matrix for the data
ByteMatrix matrix;
com.google.zxing.Writer writer = new QRCodeWriter();
try {
 matrix = writer.encode(data, com.google.zxing.BarcodeFormat.QR_CODE, width, height);
}
catch (com.google.zxing.WriterException e) {
 //exit the method
 return;
}

//generate an image from the byte matrix
int width = matrix.getWidth(); 
int height = matrix.getHeight(); 

byte[][] array = matrix.getArray();

//create buffered image to draw to
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//iterate through the matrix and draw the pixels to the image
for (int y = 0; y < height; y++) { 
 for (int x = 0; x < width; x++) { 
  int grayValue = array[y][x] & 0xff; 
  image.setRGB(x, y, (grayValue == 0 ? 0 : 0xFFFFFF));
 }
}

//write the image to the output stream
ImageIO.write(image, "png", outputStream);
//get the data from the input stream
BufferedImage image = ImageIO.read(inputStream);

//convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

//decode the barcode
QRCodeReader reader = new QRCodeReader();

Result result;
try {
 result = reader.decode(bitmap, hints);
} catch (ReaderException e) {
 //the data is improperly formatted
 throw new MCCDatabaseMismatchException();
}

byte[] b = result.getRawBytes();
System.out.println(ByteHelper.convertUnsignedBytesToHexString(result.getText().getBytes("UTF8")));
System.out.println(ByteHelper.convertUnsignedBytesToHexString(b));
// Decodes like this works perfectly
LuminanceSource ls = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap( new HybridBinarizer(ls)));
Vector byteSegments = (Vector) result.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS);  
int i = 0;
int tam = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    tam += bs.length;
}
byte[] resultBytes = new byte[tam];
i = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    for (byte b : bs) {
        resultBytes[i++] = b;
    }
}
return resultBytes;
convertUnsignedBytesToHexString(byte)
是一种将字节数组转换为十六进制字符字符串的方法

当我尝试同时运行这两个代码块时,输出如下:

48454c4c4f
202b0b78cc00ec11ec11ec11ec11ec11ec11ec

很明显,文本正在被编码,但实际的数据字节完全不存在。如果您需要任何帮助,我们将不胜感激。

因此,如果您不想花两天时间在互联网上搜索来解决这个问题,那么当您将字节数组编码为QR码时,您必须使用
ISO-8859-1
字符集,而不是
UTF-8

如果您确实需要编码UTF-8,您可以尝试预先设置unicode字节顺序标记。我不知道对这种方法的支持有多广泛,但ZXing至少似乎支持它:


最近我一直在阅读QR模式,我想我在其他地方也看到过同样的做法,但我在哪里都不知道。

我尝试使用ISO-8859-1,如第一个答案所述。编码时一切正常,但当我试图在解码时使用结果字符串获取字节[]时,所有负字节都变成了字符63(问号)。以下代码不起作用:

// Encoding works great
byte[] contents = new byte[]{-1};
QRCodeWriter codeWriter = new QRCodeWriter();
BitMatrix bitMatrix = codeWriter.encode(new String(contents, Charset.forName("ISO-8859-1")), BarcodeFormat.QR_CODE, w, h);

// Decodes like this fails
LuminanceSource ls = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap( new HybridBinarizer(ls)));
byte[] resultBytes = result.getText().getBytes(Charset.forName("ISO-8859-1")); // a byte[] with byte 63 is given
return resultBytes;
这看起来很奇怪,因为一个非常旧的版本(不确切知道)中的API有一个方法thar工作得很好:

Vector byteSegments = result.getByteSegments();
因此,我试图寻找删除此方法的原因,并意识到有一种方法可以通过元数据获取ByteSegments。因此,我的解码方法如下所示:

byte[] b = {0x48, 0x45, 0x4C, 0x4C, 0x4F};
//convert the byte array into a UTF-8 string
String data;
try {
    data = new String(b, "UTF8");
}
catch (UnsupportedEncodingException e) {
 //the program shouldn't be able to get here
 return;
}

//get a byte matrix for the data
ByteMatrix matrix;
com.google.zxing.Writer writer = new QRCodeWriter();
try {
 matrix = writer.encode(data, com.google.zxing.BarcodeFormat.QR_CODE, width, height);
}
catch (com.google.zxing.WriterException e) {
 //exit the method
 return;
}

//generate an image from the byte matrix
int width = matrix.getWidth(); 
int height = matrix.getHeight(); 

byte[][] array = matrix.getArray();

//create buffered image to draw to
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//iterate through the matrix and draw the pixels to the image
for (int y = 0; y < height; y++) { 
 for (int x = 0; x < width; x++) { 
  int grayValue = array[y][x] & 0xff; 
  image.setRGB(x, y, (grayValue == 0 ? 0 : 0xFFFFFF));
 }
}

//write the image to the output stream
ImageIO.write(image, "png", outputStream);
//get the data from the input stream
BufferedImage image = ImageIO.read(inputStream);

//convert the image to a binary bitmap source
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

//decode the barcode
QRCodeReader reader = new QRCodeReader();

Result result;
try {
 result = reader.decode(bitmap, hints);
} catch (ReaderException e) {
 //the data is improperly formatted
 throw new MCCDatabaseMismatchException();
}

byte[] b = result.getRawBytes();
System.out.println(ByteHelper.convertUnsignedBytesToHexString(result.getText().getBytes("UTF8")));
System.out.println(ByteHelper.convertUnsignedBytesToHexString(b));
// Decodes like this works perfectly
LuminanceSource ls = new BufferedImageLuminanceSource(encodedBufferedImage);
Result result = new QRCodeReader().decode(new BinaryBitmap( new HybridBinarizer(ls)));
Vector byteSegments = (Vector) result.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS);  
int i = 0;
int tam = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    tam += bs.length;
}
byte[] resultBytes = new byte[tam];
i = 0;
for (Object o : byteSegments) {
    byte[] bs = (byte[])o;
    for (byte b : bs) {
        resultBytes[i++] = b;
    }
}
return resultBytes;

这是我的工作示例Java代码,使用ZXing和UTF-8编码对QR代码进行编码,请注意:您需要将路径和utf8数据更改为您的路径和语言字符

package com.mypackage.qr;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.*;

public class CreateQR {

public static void main(String[] args)
{
    Charset charset = Charset.forName("UTF-8");
    CharsetEncoder encoder = charset.newEncoder();
    byte[] b = null;
    try {
        // Convert a string to UTF-8 bytes in a ByteBuffer
        ByteBuffer bbuf = encoder.encode(CharBuffer.wrap("utf 8 characters - i used hebrew, but you should write some of your own language characters"));
        b = bbuf.array();
    } catch (CharacterCodingException e) {
        System.out.println(e.getMessage());
    }

    String data;
    try {
        data = new String(b, "UTF-8");
        // get a byte matrix for the data
        BitMatrix matrix = null;
        int h = 100;
        int w = 100;
        com.google.zxing.Writer writer = new MultiFormatWriter();
        try {
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            matrix = writer.encode(data,
            com.google.zxing.BarcodeFormat.QR_CODE, w, h, hints);
        } catch (com.google.zxing.WriterException e) {
            System.out.println(e.getMessage());
        }

        // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                String filePath = "/Users/shaybc/Desktop/OutlookQR/qr_png.png";
        File file = new File(filePath);
        try {
            MatrixToImageWriter.writeToFile(matrix, "PNG", file);
            System.out.println("printing to " + file.getAbsolutePath());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    } catch (UnsupportedEncodingException e) {
        System.out.println(e.getMessage());
    }
}

}
package com.mypackage.qr;
导入java.io.File;
导入java.io.IOException;
导入java.io.UnsupportedEncodingException;
导入java.nio.ByteBuffer;
导入java.nio.CharBuffer;
导入java.nio.charset.CharacterCodingException;
导入java.nio.charset.charset;
导入java.nio.charset.CharsetEncoder;
导入java.util.Hashtable;
导入com.google.zxing.EncodeHintType;
导入com.google.zxing.MultiFormatWriter;
导入com.google.zxing.client.j2se.MatrixToImageWriter;
导入com.google.zxing.common.*;
公共类CreateQR{
公共静态void main(字符串[]args)
{
Charset Charset=Charset.forName(“UTF-8”);
CharsetEncoder=charset.newEncoder();
字节[]b=null;
试一试{
//将字节缓冲区中的字符串转换为UTF-8字节
ByteBuffer bbuf=encoder.encode(CharBuffer.wrap(“utf 8个字符-我使用希伯来语,但您应该编写一些自己的语言字符”);
b=bbuf.array();
}捕获(字符编码异常e){
System.out.println(e.getMessage());
}
字符串数据;
试一试{
数据=新字符串(b,“UTF-8”);
//获取数据的字节矩阵
比特矩阵=空;
int h=100;
int w=100;
com.google.zxing.Writer Writer=新的多格式编写器();
试一试{
哈希表提示=新哈希表(2);
提示.put(EncodeHintType.CHARACTER_集,“UTF-8”);
矩阵=写入器编码(数据,
com.google.zxing.BarcodeFormat.QR_码,w,h,提示);
}catch(com.google.zxing.writereException e){
System.out.println(e.getMessage());
}
//更改此路径以匹配您的路径(这是我的mac主文件夹,如果您在windows上,您可以使用:c:\\qr\u png.png)
字符串filePath=“/Users/shaybc/Desktop/OutlookQR/qr_png.png”;
文件文件=新文件(文件路径);
试一试{
MatrixToImageWriter.writeToFile(矩阵,“PNG”,文件);
System.out.println(“打印到”+file.getAbsolutePath());
}捕获(IOE异常){
System.out.println(e.getMessage());
}
}捕获(不支持的编码异常e){
System.out.println(e.getMessage());
}
}
}

值得一提的是,我的groovy spike似乎可以同时使用UTF-8和ISO-8859-1字符编码。不确定当非zxing解码器尝试解码UTF-8编码图像时会发生什么。。。可能因设备而异

// ------------------------------------------------------------------------------------
// Requires: groovy-1.7.6, jdk1.6.0_03, ./lib with zxing core-1.7.jar, javase-1.7.jar 
// Javadocs: http://zxing.org/w/docs/javadoc/overview-summary.html
// Run with: groovy -cp "./lib/*" zxing.groovy
// ------------------------------------------------------------------------------------

import com.google.zxing.*
import com.google.zxing.common.*
import com.google.zxing.client.j2se.*

import java.awt.image.BufferedImage
import javax.imageio.ImageIO

def class zxing {
    def static main(def args) {
        def filename = "./qrcode.png"
        def data = "This is a test to see if I can encode and decode this data..."
        def charset = "UTF-8" //"ISO-8859-1" 
        def hints = new Hashtable<EncodeHintType, String>([(EncodeHintType.CHARACTER_SET): charset])

        writeQrCode(filename, data, charset, hints, 100, 100)

        assert data == readQrCode(filename, charset, hints)
    }

    def static writeQrCode(def filename, def data, def charset, def hints, def width, def height) {
        BitMatrix matrix = new MultiFormatWriter().encode(new String(data.getBytes(charset), charset), BarcodeFormat.QR_CODE, width, height, hints)
        MatrixToImageWriter.writeToFile(matrix, filename.substring(filename.lastIndexOf('.')+1), new File(filename))
    }

    def static readQrCode(def filename, def charset, def hints) {
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(ImageIO.read(new FileInputStream(filename)))))
        Result result = new MultiFormatReader().decode(binaryBitmap, hints)

        result.getText()        
    }

}
//------------------------------------------------------------------------------------
//要求:groovy-1.7.6、jdk1.6.0_03、./lib和zxing-core-1.7.jar、javase-1.7.jar
//Javadocs:http://zxing.org/w/docs/javadoc/overview-summary.html
//使用:groovy-cp“/lib/*”zxing.groovy运行
// ------------------------------------------------------------------------------------
导入com.google.zxing*
导入com.google.zxing.common*
导入com.google.zxing.client.j2se*
导入java.awt.image.buffereImage
导入javax.imageio.imageio
def级zxing{
def静态干管(def args){
def filename=“./qrcode.png”
def data=“这是一个测试,看看我是否可以编码和解码此数据…”
def charset=“UTF-8”//“ISO-8859-1”
def hints=新哈希表([(EncodeHintType.CHARACTER\u SET):charset])
writeQrCode(文件名、数据、字符集、提示、100100)
断言数据==readQrCode(文件名、字符集、提示)
}
def静态写入QRCODE(def文件名、def数据、def字符集、def提示、def宽度、def高度){
BitMatrix matrix=new MultiFormatWriter().encode(新字符串(data.getBytes(charset),charset),BarcodeFormat.QR_码,宽度,高度,提示)
MatrixToImageWriter.writeToFile(矩阵,文件名.substring(文件名.lastIndexOf('.')+1),新文件(文件名))
}
def静态readQrCode(def文件名、def字符集、def提示){
BinaryBitmap BinaryBitmap=新的BinaryBitmap(新的混合二进制程序(新的BufferedImageLuminanceSource)(ImageIO.read)(新的