3

I have a hand held scanner that can read GS1-DataMatrix codes(like the ones in the supermarket). I can scan codes in Notepad++ and I can see FNC1 characters are transmited(the GS before 2210, 1D in HEX - first image)

Now I'm trying to read the same GS1 code from Java but isn't working, the FNC1 is not seen by Java. In Java I only see "01095011010209171719050810ABCD12342110". I transformed the string to HEX but the result is the same, FNC1 is not in HEX either(second image).

This is the test code:

package gs1.datamatrix;

import java.awt.Font;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

public class GS1DataMatrix {
    public static void main(String[] args) {
        JFrame f=new JFrame();//creating instance of JFrame  
        Font font = new Font("Courier New", Font.PLAIN, 16);

        JTextArea jtf2 = new JTextArea(); // used to hold the HEX data
        jtf2.setBounds(10,250,900, 200);
        jtf2.setFont( font.deriveFont( 24.0f) );
        jtf2.setLineWrap(true);
        f.add(jtf2);//adding button in JFrame  

        JTextArea jtf1 = new JTextArea(); // scan area for the DataMatrix scanner
        jtf1.setBounds(10,10,900, 200);
        jtf1.setFont( font.deriveFont( 24.0f) );
        jtf1.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {                update(e);            }
            @Override
            public void removeUpdate(DocumentEvent e) {                update(e);            }
            @Override
            public void changedUpdate(DocumentEvent e) {                update(e);            }
            public void update(DocumentEvent e) {
                try {
                    Document doc = (Document)e.getDocument();
                    String hex = String.format("%040x", new BigInteger(1, doc.getText(0, doc.getLength()).getBytes("UTF8"))); // transform to HEX
                    jtf2.setText(java.util.Arrays.toString(hex.split("(?<=\\G..)"))); // split hex data by 2 characters
                    jtf1.selectAll();
                } catch (Exception ex) {
                    Logger.getLogger(GS1DataMatrix.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        f.add(jtf1);//adding button in JFrame  

        f.setSize(1000,500);
        f.setLayout(null);
        f.setVisible(true);
    }
}

First image: this is how Notepad++ reads FNC1(GS special character on black background):

n++

Second image: this is Java result: enter image description here

Third image: Notepad++ hex dump showing FNC1 as 1D in HEX at every scan:

enter image description here

Later edit I think there has been a confusion caused by my original post: I don't parse images, the scanner has build in hardware that does this for me and I only receive a text and some special characters(FNC1's).

4

1 回答 1

2

阅读后的一些猜测:

  • FNC1 没有标准表示。 这个 stackoverflow 答案表明,没有办法在用于传输的默认 Latin-1 编码中直接对 FNC1 进行编码。作为一种解决方法,大多数读者似乎默认使用 ASCII 控制字符“组分隔符”(GS、29、0x1d)。

  • 您正在使用摆动控件来显示和处理数据。Swing 主要用于显示目的,而不是用于正确的数据处理目的。
    我假设发生的情况是当它在 JTextArea 的内容中设置时,swing 会剥离不可打印的 GS 字符

考虑到您对扫描仪传输数据的确切方式并不十分明确,但您提到“它更像键盘”,我假设扫描仪通过假装是键盘来传输数据。您将选择输入,按下扫描仪上的按钮,它将以按键的形式发送数据。

现在如果是这种情况,您将无法使用 SwingDocumentListener/Document解决此问题。以下堆栈溢出问题基本上是指您遇到的相同问题(不同之处在于他们使用的是 qrcode 而不是条形码):ASCII Non printable characters in textcomponent

现在我链接的问题表明您可以使用 aKeyBinding或 KeyListener 来解决此问题。请注意,如果您想打印不可打印的字符,这将以某种方式破坏十六进制表示。

UTF-8 确实有一个用于 ASCII 不可打印字符表示的特殊代码点。“组分隔符的符号”位于\u241d。处理这个问题的一个选项是:

jtf1.getInputMap().put(KeyStroke.getKeyStroke(29), "handleGS");
jtf1.getActionMap().put("handleGS", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        jtf1.setText(jtf1.getText() + "\u241d");
    }
}

这样十六进制表示应该变成:

.. , 33, 34, e2, 90, 9d, 32, 31, 31, 30]

请注意,因为我们将 GS 重新映射到 Unicode 的“SYMBOL_FOR_GS”,所以我们得到e2, 90, 9d的不是1d.

于 2018-11-19T10:53:43.953 回答