我有一个手持扫描仪,可以读取 GS1-DataMatrix 代码(就像超市里的那种)。我可以在 Notepad++ 中扫描代码,我可以看到传输了 FNC1 字符(2210 之前的 GS,十六进制中的 1D - 第一张图片)
现在我正在尝试从 Java 读取相同的 GS1 代码,但无法正常工作,Java 看不到 FNC1。 在 Java 中,我只看到“01095011010209171719050810ABCD12342110”。 我将字符串转换为十六进制,但结果是一样的,FNC1 也不在十六进制中(第二张图片)。
这是测试代码:
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);
}
}
第一张图:Notepad++ 是这样读取 FNC1(黑色背景上的GS 特殊字符)的:
第三张图片:Notepad++ 十六进制转储在每次扫描时显示 FNC1 为十六进制的 1D:
稍后编辑 我认为我的原始帖子引起了困惑:我不解析图像,扫描仪内置硬件为我做这件事,我只收到文本和一些特殊字符(FNC1)。
最佳答案
经过一番阅读后的一些猜测:
FNC1 没有标准表示。 This stackoverflow answer表明没有办法在用于传输的默认 Latin-1 编码中直接对 FNC1 进行编码。 作为解决方法,大多数读者似乎默认使用 ASCII 控制字符“组分隔符”(GS, 29, 0x1d)。
您正在使用 Swing 控件来显示和处理数据。 Swing 主要用于显示目的,而不是用于正确的数据处理目的。
我假设发生的情况是,当 swing 设置在 JTextArea 的内容中时,它会剥离不可打印的 GS 字符
考虑到您对扫描仪传输数据的确切方式并不是非常明确,但您提到“它更像是键盘”,我假设扫描仪通过假装是键盘来传输数据。 您将选择输入,按下扫描仪上的按钮,它会以按键的形式发送数据。
现在如果是这种情况,您将无法使用 Swing 的 DocumentListener/Document
来解决这个问题。
以下 Stack Overflow 问题基本上指的是您遇到的相同问题(不同之处在于他们使用的是二维码而不是条形码):ASCII Non printable characters in textcomponent
现在我链接的问题表明您可以使用KeyBinding
或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
。
关于java - 如何在 Java JTextArea 中读取 FNC1 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53248562/