Java上的条形码扫描仪实现[关闭]

Posted

技术标签:

【中文标题】Java上的条形码扫描仪实现[关闭]【英文标题】:Barcode Scanner implementation on Java [closed] 【发布时间】:2011-12-30 02:48:12 【问题描述】:

好先生,我有一个问题。我目前正在从事的学校 Java 项目要求我将 USB 条形码扫描仪作为外部输入连接到我的笔记本电脑。我实际上并没有购买 USB 扫描仪,因为它对学生来说相当昂贵。所以我必须收集证据证明这个扫描仪可以和我的程序一起工作。

扫描仪能否读取条形码(可能是在线打印的)并将其存储到变量中?如果是这样,按下扫描仪的动作事件是否会像键盘按键一样被读取?如果是这样,代码行会是什么样子?

此外,如果您可以发布您使用条形码扫描仪的经验,或提供任何建议,例如购买哪种扫描仪,那将很有帮助。干杯!

【问题讨论】:

如果您的光标位于文本框或输入字段中,扫描仪只会在此处“写入”代码。扫描仪没有什么特别之处。你不会得到一个事件。但是如果你有一个网页,你可以尝试类似 JS 的 'OnChange' 事件。 【参考方案1】:

我最近不得不实现一个扫描系统来与 java 交互。

我使用的是 Honeywell Voyager MS9540 USB 条码扫描器。

默认情况下,扫描仪直接将数据作为键盘输入发送 - 无需驱动程序。

但是很容易让这个模型直接与java交互,而不是使用键盘钩子(在java中使用条形码作为变量,正如你提到的)。

这个模型有一个模拟串口的设置,然后你可以使用 javax.comm 包读取扫描的数据。对我来说,这比获取条形码数据的键盘挂钩要好得多,因为程序在能够解释扫描之前不需要焦点(我不想创建全局键盘挂钩) .

我的 java 程序从指定的串行端口读取所有输入并将条形码写入数据库。我还设置了程序以将任何无法识别的条形码扫描传递到键盘(我的应用程序未创建的任何条形码 - 我在我的条形码上使用了独特的签名),这样它就可以作为任何其他可能的应用程序的常规条形码扫描仪从键盘读取条形码。

通过执行一些密集的 JNI 编码,您可能可以直接从任何 USB 扫描仪读取数据(无需此模型具有的串行端口仿真),但我不准备花时间编写本机代码。

要为串行端口仿真配置此特定型号,您只需使用您要配置的扫描仪扫描this 文档中的特定条形码。它是标题为“串行仿真模式”的条形码。

此扫描仪确实需要用于串行端口仿真的驱动程序。我找到了实现说明和所需的驱动程序here(在“软件”选项卡下)。下载标题为“Honeywell Scanning and Mobility (HSM) USB Serial Driver”的软件包。标题为“HSM USB 串行驱动程序入门指南”的 PDF 有说明。

如果您不熟悉 javax.comm API。请阅读 Rick Proctor 的 this 示例中的介绍 - 它告诉您从哪里获取 jar 以及将文件放在哪里(javax.comm 不是大多数 java 包的标准配置)。

我确信周围还有其他具有串行端口仿真功能的扫描仪型号(我不为霍尼韦尔工作)。

这是我的条码阅读器类的精简版:

package scanhandler;


import java.awt.AWTException;
import java.awt.Robot;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

public class ScanHandler implements Runnable, SerialPortEventListener 

    private static CommPortIdentifier   myCommPortIdentifier;
    private static Enumeration          portList;
    private static String               TimeStamp;
    private static String               driverClass;
    private static String               connectionString;
    private static String               comPort;    

    private Connection                  myConnection;
    private InputStream                 myInputStream;
    private Robot                       myRobot;
    private SerialPort                  mySerialPort;
    private Thread                      myThread;


    public ScanHandler() 

        // open serial port
        try 
            TimeStamp = new java.util.Date().toString();
            mySerialPort = (SerialPort) myCommPortIdentifier.open("ComControl", 2000);
            //System.out.println(TimeStamp + ": " + myCommPortIdentifier.getName() + " opened for scanner input");
         catch (PortInUseException e) 
            e.printStackTrace();
        

        // get serial input stream
        try 
            myInputStream = mySerialPort.getInputStream();
         catch (IOException e) 
            e.printStackTrace();
        

        // add an event listener on the port
        try 
            mySerialPort.addEventListener(this);
         catch (TooManyListenersException e) 
            e.printStackTrace();
        
        mySerialPort.notifyOnDataAvailable(true);

        // set up the serial port properties
        try 
            mySerialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);
            mySerialPort.setDTR(false);
            mySerialPort.setRTS(false);

         catch (UnsupportedCommOperationException e) 
            e.printStackTrace();
        

        // make a robot to pass keyboard data
        try 
            myRobot = new Robot();
         catch (AWTException e) 
            e.printStackTrace();
        

        // create the thread
        myThread = new Thread(this);
        myThread.start();
    

    public void run() 
        try 
            Thread.sleep(100);
         catch (InterruptedException e) 
    

    // on scan
    public void serialEvent(SerialPortEvent event) 

        if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) 

            StringBuilder myStringBuilder = new StringBuilder();
            int c;
            try 

                // append the scanned data onto a string builder
                while ((c = myInputStream.read()) != 10)
                   if (c != 13)  myStringBuilder.append((char) c);
                               

                // send to keyboard buffer if it the barcode doesn't start with '5'
                if (myStringBuilder.charAt(0) != '5') 

                    for (int i = 0; i < myStringBuilder.length(); i++) 
                        myRobot.keyPress((int) myStringBuilder.charAt(i));
                        myRobot.keyRelease((int) myStringBuilder.charAt(i));
                    

                // here's the scanned barcode as a variable!
                 else 
                    TimeStamp = new java.util.Date().toString();
                    System.out.println(TimeStamp + ": scanned input received:" + myStringBuilder.toString());                    
                

                // close the input stream
                myInputStream.close();

             catch (IOException e) 
                e.printStackTrace();
            
        
    

    public static void main(String[] args) 

        // read ScanHandler properties
        Properties myProperties = new Properties();
        try 
            myProperties.load(new FileInputStream("config.properties"));
            comPort             = myProperties.getProperty("ScanHandler.comPort");
         catch (IOException e) 
            e.printStackTrace();
                      

        try 

            // get our pre-defined COM port
            myCommPortIdentifier = CommPortIdentifier.getPortIdentifier(comPort);
            ScanHandler reader = new ScanHandler();

         catch (Exception e) 
            TimeStamp = new java.util.Date().toString();
            System.out.println(TimeStamp + ": " + comPort + " " + myCommPortIdentifier);
            System.out.println(TimeStamp + ": msg1 - " + e);
        
    ;    

【讨论】:

看起来这些驱动程序仅适用于 Windows,因此如果您这样做,您将无法在 Windows 以外的其他操作系统上使用您的程序。 可能是对的,我只在 windows 上需要这个。我没有深入搜索,但应该有一些东西可以将 USB 转换为 Linux 或 MAC 的 COM 端口 @Geronimo:从哪里可以找到这个 config.properties 文件。 @ShirgillAnsari 我认为示例代码从 config.properties 中读取的唯一内容是 com 端口,例如:“COM1”、“COM2”、“COM3”等,无论您的条形码扫描仪的串行端口如何已连接到 这段代码是用USB口还是串口?【参考方案2】:

我意识到这是一个老问题,但我想我会添加一个额外的解决方案来模拟条形码扫描仪输入。此解决方案仅适用于将扫描仪输入模拟为键盘数据。

由于扫描仪通常只使用键盘输入,我们可以使用AutoHotkey 脚本来模拟它。下面是一个脚本示例:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Barcode 1
; Hotkey = ctrl + alt + 1
^!1::
    SendInput [BC200015]
Return

; Barcode 2
; Hotkey = ctrl + alt + 2
^!2::
    SendInput [BC300013]
Return

只需将[BC300013][BC200015] 替换为您预期的扫描仪输入即可。

【讨论】:

【参考方案3】:

我知道这是很老的帖子,但搜索可以让你到达那里。

这可以被视为对 Geronimo 答案的补充:

对于 Linux 操作系统,无需为串行仿真模式下的条码扫描器安装驱动程序,因为本机支持 USB 串行端口。我们使用了几种类型的 Honeywell 扫描仪,它们都开箱即用,串行仿真中的扫描仪在我们的系统中显示为 /dev/ttyACM0、/dev/ttyACM1 等。

最近我们已经从 javax.comm 切换到 jssc 作为一个 java 库来接口串行端口。如果我没记错的话,在 Windows 7 64 位系统下,javax.comm 库无法读取或写入串口,而 jssc 有非常相似的 api。

【讨论】:

欢迎来到***。请尝试从编辑器中格式化您的答案。【参考方案4】:

我使用的条形码扫描仪就像一个键盘设备(它在操作系统中显示为 HID 键盘 USB 设备)。当条形码被扫描时,它会像输入一样发送代码。无需特殊的 API 即可与之交互。

【讨论】:

请问你买的是什么型号的? @user976123 这是几年前的一份工作,抱歉我不记得型号是什么了。

以上是关于Java上的条形码扫描仪实现[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

我想用java设计一个条形码扫描器,将扫描的数字在数据库中查找详细信息,请问如何实现?解决有+

Android:如何将通过USB连接的外部条形码扫描仪设备集成到Android应用程序[关闭]

JAVA实现多种类型条形码的生成与扫描

.net 手机扫描二维码功能

使用 Kivy 读取条码扫描器

PhoneGap 条码扫描器插件 - 相机关闭