【问题标题】:How to read FNC1 characters in Java JTextArea如何在 Java JTextArea 中读取 FNC1 字符
【发布时间】:2018-11-11 12:06:09
【问题描述】:

我有一个可以读取 GS1-DataMatrix 码的手持式扫描仪(就像超市里的那种)。我可以在 Notepad++ 中扫描代码,我可以看到 FNC1 字符被传输(2210 之前的 GS,HEX 中的 1D - 第一张图像)

现在我正在尝试从 Java 读取相同的 GS1 代码,但无法正常工作,Java 看不到 FNC1。 在 Java 中,我只看到“01095011010209171719050810ABCD12342110”。 我将字符串转换为 HEX,但结果相同,FNC1 也不在 HEX 中(第二张图片)。

这是测试代码:

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 黑色背景上的特殊字符):

第二张图片:这是 Java 结果:

第三张图片:Notepad++ 十六进制转储在每次扫描时将 FNC1 显示为十六进制中的一维:

稍后编辑 我认为我的原始帖子引起了混淆:我不解析图像,扫描仪内置了为我执行此操作的硬件,我只收到文本和一些特殊字符(FNC1)。

【问题讨论】:

  • 如何将文本放入jtf1 文本区域?通过复制和粘贴?来自哪个其他应用程序?你的操作系统是什么?您的操作系统使用哪种语言环境/字符编码?在 Java 看到内容之前可能会出现许多故障点,尤其是在涉及 GUI 组件/其他应用程序的情况下。
  • 我从手持条形码扫描仪获取文本,WIN 10/64 位,语言是英语(美国)。我使用 Netbeans 启动 Java 1.8,并使用选项 -Dfile.encoding=UTF-8 启动 Java。我倾向于同意你的看法——这一定是操作系统问题。我下载了 javahexeditor 可执行文件,这里的 FNC1 字符很好,但是当我下载 javahexeditor 源代码并在 Netbeans 中运行它时,FNC1 消失了。我可能必须在 JavaVM 环境中设置一些东西 - 我还不知道。
  • 请注意,通常称为 FNC1 字符的不是 GS 字符(实际上是一维字符)。通常 FNC1 字符是开始序列的字符。我不记得价值,但 GS1 规格可能会有所帮助。剩下的对不起,我不是java人^^
  • 根据 GS1 指南第 2.2.1 节,FNC1 用作起始字符和分隔符。但是启动 FNC1 永远不会发送到计算机,只是在条码扫描仪内部用于识别 GS1 代码。这可能不是严格意义上的 Java 问题。 gs1.org/docs/barcodes/GS1_DataMatrix_Guideline.pdf

标签: java gs1-datamatrix


【解决方案1】:

阅读后的一些猜测:

  • FNC1 没有标准表示。 This stackoverflow answer 建议无法直接将 FNC1 编码为用于传输的默认 Latin-1 编码。 作为一种解决方法,大多数读者似乎默认使用 ASCII 控制字符“组分隔符”(GS、29、0x1d)。

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

考虑到您并没有非常明确地说明您的扫描仪如何准确地传输数据,但您提到“它更像是一个键盘”,我假设扫描仪通过伪装成键盘来传输数据。 您将选择输入,按下扫描仪上的按钮,它会以按键的形式发送数据。

如果是这种情况,您将无法使用 Swing 的 DocumentListener/Document 来解决此问题。 以下 Stack Overflow 问题基本上是指您遇到的相同问题(不同之处在于他们使用的是 qrcode 而不是条形码):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

【讨论】:

  • 谢谢。我试过了,但没有什么不同,可能代码 29 不在原文中。我测试了代码并且很好,当我用 49 替换 29 时,所有出现的“1”都以 \u241d 开头。我从这里得到了 1(49) 的代码:cambiaresearch.com/articles/15/javascript-char-codes-key-codes 代码中唯一的变化是 getKeyStroke 中的第二个参数:KeyStroke.getKeyStroke(49, 0)
  • 我实际上尝试了从十进制 0 到十进制 31 的所有不可打印字符,但没有一个匹配。我知道这没有任何意义 - 尝试从 0-31 的所有代码,但我试过了,我不确定我还能尝试什么。 asciitable.com
  • 源代码很好,FNC1的代码实际上是144。
猜你喜欢
  • 2014-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 1970-01-01
  • 2012-12-02
  • 1970-01-01
相关资源
最近更新 更多