如何使用BitMatrix对象序列化HashMap? (QR码/ zxing)

时间:2016-09-23 10:38:07

标签: java serialization qr-code zxing

我有一个名为QRGenerator的“静态类”,其目的是生成BitMatrix对象并从中生成BufferedImage对象。这是它的代码:

package ericsonwrp.republica.vintage.caixa;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRGenerator {

    private static BufferedImage image = null;
    private static int size = 250;
    private static BitMatrix byteMatrix = null;

    public static BitMatrix generateBitMatrix(String codeText) {
        try {
            Map<EncodeHintType, Object> hintMap = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
            hintMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hintMap.put(EncodeHintType.MARGIN, 1);
            hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            byteMatrix = qrCodeWriter.encode(codeText, BarcodeFormat.QR_CODE, size,
                    size, hintMap);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return byteMatrix;
    }

    public static BufferedImage generateImage(BitMatrix byteMatrix) {
        int width = byteMatrix.getWidth();
        image = new BufferedImage(width, width,
                BufferedImage.TYPE_INT_RGB);
        image.createGraphics();
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, width);
        graphics.setColor(Color.BLACK);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < width; j++) {
                if (byteMatrix.get(i, j)) {
                    graphics.fillRect(i, j, 1, 1);
                }
            }
        }
        return image;
    }

}

我有另一个名为“RepublicaVintageFile”的类,其目的是定义一个唯一的文件来存储我的应用程序的“内容”,并提供一种序列化的方法(和读取,这与问题无关)这个“内容”。这是它的代码:

package ericsonwrp.republica.vintage.caixa;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.HashMap;

public class RepublicaVintageFile {

    private HashMap<String, Object> content;

    public RepublicaVintageFile() {
        setContent(new HashMap<String, Object>());
    }

    public void serializeContent(String path) throws IOException {
        FileOutputStream fout = new FileOutputStream(path, true);
        ObjectOutput out = null;
        try {
          out = new ObjectOutputStream(fout);   
          out.writeObject(getContent());
        } finally {
          try {
            if (out != null) {
              out.close();
            }
          } catch (IOException ex) {
            // ignore close exception
          }
          try {
            fout.close();
          } catch (IOException ex) {
            // ignore close exception
          }
        }
    }

    public HashMap<String, Object> getContent() {
        return content;
    }

    public void setContent(HashMap<String, Object> content) {
        this.content = content;
    }

}

我的应用程序的“内容”包括BitMatrix对象,它们保存在HashMap内的标签下的不同文件(private HashMap<String, BitMatrix> qrItems;)中。由于序列化最终的BufferedImage给了我一个java.io.NotSerializableException,我试图序列化BitMatrix对象。但是,令我失望的是,这也是不可能的。这是堆栈跟踪:

java.io.NotSerializableException: com.google.zxing.common.BitMatrix
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.HashMap.internalWriteEntries(Unknown Source)
    at java.util.HashMap.writeObject(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at java.util.HashMap.internalWriteEntries(Unknown Source)
    at java.util.HashMap.writeObject(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at ericsonwrp.republica.vintage.caixa.RepublicaVintageFile.serializeContent(RepublicaVintageFile.java:26)
    at ericsonwrp.republica.vintage.caixa.MainFrame.openSaveAsDialog(MainFrame.java:204)
    at ericsonwrp.republica.vintage.caixa.MainFrame.access$1(MainFrame.java:177)
    at ericsonwrp.republica.vintage.caixa.MainFrame$4.actionPerformed(MainFrame.java:112)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.AbstractButton.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

考虑到这一切,我提出了一个问题:如何使用BitMatrix对象序列化HashMap?这很重要,因为我不想在文件夹上存储100个(或更多)单独的.png文件,并且必须一直读取图像以获取其内容。

1 个答案:

答案 0 :(得分:0)

我设法“保存”并“加载”BitMatrix对象,将它们转换为布尔的二维数组。

private HashMap<String, BitMatrix> qrMatrixes;
private HashMap<String, boolean[][]> qrMatrixBooleanArrays;

如您所见,我的HashMap为&lt; String,BitMatrix&gt;,具有boolean [] []格式的等价物。这就是我如何进行这种“翻译”(将每个BitMatrix对象的位转移到布尔[] []数组中):

for (Map.Entry<String, BitMatrix> e : getQrMatrixes().entrySet()) {
    boolean[][] b = new boolean[e.getValue().getHeight()][e.getValue().getWidth()];
    for (int j = 0; j < e.getValue().getHeight(); j++) {
        for (int k = 0; k < e.getValue().getWidth(); k++) {
            b[j][k] = e.getValue().get(j, k);
        }
    }
    qrMatrixBooleanArrays.put(e.getKey(), b);
}

Java的Serializer序列化这样的对象(HashMap&lt; String,boolean [] []&gt;)没有任何问题,无论它是如何嵌套的(我已经想到它可以使用原始类型,使用老式数组)。以下是加载文件后用QR码更新列表的整个方法:

    public void updateList() {
        if (MainFrame.getCurrentFile() != null) {
            setQrMatrixes(new HashMap<String, BitMatrix>());
            setQrMatrixBooleanArrays(new HashMap<String, boolean[][]>());
            for (Map.Entry<String, boolean[][]> e : ((HashMap<String, boolean[][]>) MainFrame.getCurrentFile().getContent().get("Qr Codes")).entrySet()) {
                getQrMatrixBooleanArrays().put(e.getKey(), e.getValue());
            }
            for (Map.Entry<String, boolean[][]> e : getQrMatrixBooleanArrays().entrySet()) {
                BitMatrix b = new BitMatrix(e.getValue().length, e.getValue().length);
                for (int i = 0; i < e.getValue().length; i++) {
                    for (int j = 0; j < e.getValue()[i].length; j++) {
                        if (e.getValue()[i][j] == true) {
                            b.set(i, j);
                        }
                    }
                }
                getQrMatrixes().put(e.getKey(), b);
                qrListModel.addElement(e.getKey());
            }
        } else {
            System.out.println("No file is loaded.");
        }
    }

我担心要更清楚有点难。 Explore the docs用于BitMatrix对象,只需将内容复制到原始的2d数组中。祝你好运!