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).

Victorqedu
  • 484
  • 4
  • 20
  • 1
    How do you get the text into the `jtf1` text area? By Copy&Paste? From which other application? What's your Operating System? Which locale / character encoding does your OS use? There can be many points of failure before Java even sees the contents, especially if GUI components / other applications are involved. – Ralf Kleberhoff Nov 11 '18 at 13:27
  • I get the text from a hand held, barcode scanner on a WIN 10/64 bit on wich language is english(US). I start Java 1.8 with Netbeans and I start Java with the option -Dfile.encoding=UTF-8. I tend to agree with you - this must be a OS problem. I downloaded javahexeditor executable and here FNC1 chars are fine, but when I downloaded javahexeditor source code and runned it in Netbeans, FNC1 dissapeared. I probably must set something in JavaVM environment - I don't know what yet. – Victorqedu Nov 11 '18 at 15:10
  • Just a quick note, what is usually named FNC1 char is not the GS char (which is 1D in effect). Usually FNC1 character is the one starting the sequence. I don't remember the value but GS1 spec may help. For the rest sorry I'm not a java guy ^^ – Mikitori Nov 12 '18 at 17:04
  • According to GS1 Guideline, section 2.2.1, FNC1 is used as a start character and as a separator character. But the start FNC1 is never send to the computer, is just used internaly by the barcode scanners to recognize GS1 codes. This is probably not a strictly Java problem. https://www.gs1.org/docs/barcodes/GS1_DataMatrix_Guideline.pdf – Victorqedu Nov 13 '18 at 05:04
  • Check this [GS1 DataMatrix codes in Java](https://blog.jayway.com/2016/06/30/gs1-datamatrix-codes-java/) – Victor Gubin Nov 15 '18 at 11:55
  • Thank you but I don't use images, I use a hand held scanner like the ones in the super market not like the scannes that scan a paper and send it to the computer as jpg. The image is hardware processed in the scanner and I receive text with some special characters. It's more like a keyboard that like a scanner. – Victorqedu Nov 16 '18 at 02:34

1 Answers1

2

Some guesses after reading around a bit:

  • FNC1 does not have a standard representation. This stackoverflow answer suggests that there is no way to directly encode FNC1 in the default Latin-1 encoding used for transmission. As a workaround, most readers seem to default to the ASCII control character "Group Separator" (GS, 29, 0x1d).

  • You are using a swing control to display and work with the data. Swing is primarily intended for displaying purposes, not for correct data handling purposes.
    I assume what happens is that swing strips the non-printable GS character when it's set within the content of the JTextArea

Considering that you're not terribly explicit about how exactly your scanner transfers the data, but you mention "It's more like a keyboard", I assume the scanner transfers the data by pretending to be a keyboard. You'd be selecting the input, pressing a button on the scanner and it would send data as keypresses.

Now if that is the case, you won't be able to use Swing's DocumentListener/Document to solve this. The following Stack Overflow question basically refers to the same problem that you have (with the difference that they're using a qrcode instead of a barcode): ASCII Non printable characters in textcomponent

Now the question I linked suggests that you can use a KeyBinding or a KeyListener to fix this. Note that this will in some way break the hexadecimal representation, if you want to print the non-printable character.

UTF-8 does have a special codepoint for ASCII non-printable character representations. The "Symbol for Group Separator" is located at \u241d. An option to handle this would then be:

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

That way the hexadecimal representation should become:

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

Note that because we remapped the GS to Unicode's "SYMBOL_FOR_GS", we get e2, 90, 9d instead of 1d.

Vogel612
  • 5,620
  • 5
  • 48
  • 73
  • Thank you. I tried but nothing different heappened, maybe code 29 is not in the original text. I tested the code and is fine, when I replaced 29 with 49 all occurences of "1" were preceded by \u241d. I got the code for 1(49) from here: https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes The only change in your code was the second parameter in getKeyStroke: KeyStroke.getKeyStroke(49, 0) – Victorqedu Nov 20 '18 at 16:05
  • I acctually tried all non printable characters from decimal 0 to decimal 31 and none matched. I know this has no sense - to try all codes from 0-31 but I tried, I'm not sure what else can I try. http://www.asciitable.com/ – Victorqedu Nov 20 '18 at 18:46
  • The source code was fine, the code for FNC1 is acctualy 144. – Victorqedu Nov 25 '18 at 06:49