读取条形码

 

(摘选: http://www.ibm.com/developerworks/cn/java/j-i-barcd/index.html)

简介

观察一下您的周围。您看到了什么?如果您是众多软件程序员中的一名,您所看到的不会太好。 然而,我们不谈论您的同事;我们谈论条形码。因为飞速发展的经济已经迅速地采用了条形码提供的便利, 所以它们已经普遍存在。从跟踪邮包到借阅图书馆书籍,条形码无处不在。

在本文中,我们仔细研究这些类似斑马(有黑白条纹)的东西, 并向您显示如何使用 Java 来促进和组织围绕 IBM DB2 数据库的企业运营。

为了继续阅读本文,可以下载 jmart.jar 代码文件和必需的通信端口文件 barcode.zip

条形码研究

有许多不同类型的条形码。在本文中,我们只关注一种 ― UPC 条形码。UPC 代表通用产品代码(Universal Product Code)。 最初创建这些代码是为了促进杂货店收款处的运营和跟踪库存。由于它们的成功,这个想法就象野火般迅速传播到其它零售产品。

商品的 UPC 实际上是由一家名为 Uniform Code Council(UCC)的公司发布的。您基本上可以将 UCC 作为代理, 以确保两个不同产品不会有相同的 UPC 代码。制造商必须向 UCC 提出申请并缴付年费,才能得到进入其系统的许可。作为交换,UCC 发给制造商一个制造商标识号。

UPC 符号通常有两个部分:

  • 机器可读的条形码
  • 人类可读的 12 位 UPC 号码

前 6 位 UPC 号码是 制造商标识号 。接下来 5 位是 产品编号 。制造商负责确保其任何两种产品不会有相同的产品编号。 制造商销售的每件产品都必需有不同的产品编号。如果涉及到不同尺寸的产品包装或重新包装,那么这些情况也需要其自己的唯一产品编号。

至此,我们只说明了 12 位 UPC 号码中的 11 位。最后一位是 校验位 。 在没有深入钻研条形码科学的情况下,让我们姑且认为最后一位确保所扫描的 UPC 符号是准确的。 这时,您可能想要停止并细察得到的每个 UPC 代码。 注:您看到的一些 UPC 代码可能没有 12 位;短的那些称为消零条形码。本文中出现的代码本身不处理短条形码, 但您应该能够方便地改写我们的代码以用于缩写的 UPC 代码。

项目概述

现在,继续我们的项目。存储在 UPC 代码中的唯一信息是制造商编号和产品编号。当前价格和数量这种有意义的信息没有存储在 UPC 符号中。这样做并不巧妙,因为这种设置无法适应价格变化和库存变化。 那么如何起作用呢?当收款处的扫描器扫描 UPC 代码时, 收银机将已扫描的 UPC 代码信息发送到销售点(POS)计算机。然后,POS 计算机返回有关已扫描商品的预编程信息, 它可以包括当前价格、数量和其它请求信息。

BarCodeScanner 项目的目的是模拟上一段落中描述的设置。我们的代码将与来自可以挂接到串口的扫描器的数据一起工作。 使用该数据,您将能够执行营业员在当地杂货店所做的工作。我们将友好的邻近杂货店称为 J*Mart。IBM DB2 数据库将充当后端,存储每件商品的信息。干脆让我们立即开始。

后端

我们将 DB2 数据库用做后端,将它称为 销售点 (或 POS)数据库。接着, 通过激活 DB2 命令行并发出下列语句来创建您的数据库:

CREATE DB POSDB

下一步,需要一个表来存储数据。下表显示数据库中可能需要的项目:

特性名 示例值 数据库列名 列类型
产品编号12345ITEMNUMBERInteger
制造商标识号123456MANUFACTURERNUMBERInteger
产品名DoritosNAMEVarchar(40)
制造商名称Frito-LayMANUFACTURERNAMEVarchar(40)
数量23QUANTITYInteger
价格1.67PRICEDecimal(5,2)

发出下列语句来创建该表:

Create Table posTable (Itemnumber Integer NOT NULL, ManufacturerNumber Integer NOT NULL, name varchar(40) NOT NULL, manufacturerName varchar(40) NOT NULL, quantity Integer NOT NULL, Price decimal(5,2) NOT NULL)

请注意,所有这些数据库列都要求新记录没有空值。

前端将能够以许多种不同方法与数据库交互:

  • 可以将新产品输入数据库
  • 可以更新现有产品的数量
  • 可以从 POS 数据库完全除去产品
  • 可以在数据库中获取关于现有产品的信息

要完成这些任务,Java 程序使用 Java 数据库连接(JDBC)来与 IBM DB2 数据库交互。 此时,查看 com.jmart.dbaccess下载 JAR 文件 ,如果还未下载的话)中的代码对您会有帮助。 尤其是,类 Database 是方便至 DB2 数据库连接的助手类。 DatabaseAccess 类具有函数 delInventory、qryInventoryupdInventory 。 代码载有文档,所以您应该能够不花费很大的气力就可以弄清发生了什么。

方法有一个入参类型 InventoryDataInventoryData 类是 com.jmart.data 包的一部分,该类在整个项目中用做临时存储工具,以来回传送数据。 在 Java 程序员术语中, InventoryData 类可以被认作 JavaBean 组件。 类充当通信管道。在整个代码中,我们充分利用了 Java 中的对象按引用传递这一事实。

必需的通信端口文件

要使 BarCodeScanner 运行,下载 barcode.zip 文件并正确安装压缩文件。

comm.jar ― 包含运行 BarCodeScanner 和使用串或并口的其它应用程序所需的类。 确保运行应用程序时类路径指向这个 JAR 文件。

javax.comm 特性 ― 将这个文件放在 jre 的 lib 目录中。

win32comm.dll ― 将这个文件放在 Windows 目录(例如,c:\Windows)下。

要使该程序在其它操作系统上运行,请搜索您需要的 dll 文件。

扫描概述

不管您信不信,条形码扫描已相当标准化。现在,您可以购买挂接到 PC COM 端口的手持式扫描器。 扫描器将信号发送到 COM 端口,该端口可由被指定侦听进入流的程序获取。侦听工具在 Java 世界中相当原始; 但这种原始使我们的生活更方便。将进入的扫描作为字节数组写入串口, 由程序员决定将它转换成有用信息。

BarCodeScanner 本身的实现并不十分困难。我们知道将要获得信息, 并知道我们的工作是将它转换成可以解析信息的有用字符串。 javax.comm 包提供了从串口或并口收集该信息所需的框架。 (有关 javax.comm 包的更多信息,请参阅 参考资料 。)

javax.comm 包完全是其处理端口以及如何从端口检索信息的基本要素。 现在是 21 世纪,从 1998 以来,OO 已经发展了很长一段时间。 因此,要使条形码扫描器的行为象其它已建立的 Java 设计模型那样,我们为条形码创建了当扫描每个条形码时发出 BarCodeEvent 的事件/侦听器模型。从这个意义上讲,可以将条形码扫描器视作并编码成按钮按下或鼠标单击。现在,从代码开始…。

BarCodeScanner

BarCodeScanner 类的构造器负责创建端口并设置条形码扫描器将使用的所有参数。 大多数情况下,可以根据使用的条形码扫描器来更改这些设置。 检查条形码扫描器设置并对代码进行相应的调整,或者(最好)从代码中除去它们并将它们放在特性文件中。


BarcodeScanner 构造器

CommPortIdentifier commPort = CommPortIdentifier.getPortIdentifier("COM1");
serialPort = (SerialPort)commPort.open("Barcode Scanner",3000);
inputStream = new BufferedReader (new InputStreamReader
  (new BufferedInputStream(serialPort.getInputStream())));
serialPort.setInputBufferSize(200);
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8,
  SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

 

既然串口是打开的并且正在侦听,那么我们就必须准备好接收和解释条形码读取。 javax.comm 为端口提供它自己的事件/侦听器接口,即通知该类已将数据放入缓冲区的 serialEvent() 方法。 现在由您决定处理该代码。

我们使用输入流来将字节数组转换成 String。但是,我们发现当使用不同的条形码扫描器和条形码时有下列问题。

  • 当处理大于 100 个字符的大条形码时,会发出两个 serialEvent: 第一个 serialEvent 的缓冲区只被部分填充,第二个 serialEvent 的缓冲区被完全填充。 解决这个问题的最简单方法是当缓冲区中的数据不完整时忽略该事件,并等待直到它完整为止才将它传递到侦听器。
    	if (inputStream.available() < length)
    	    return;

  • 某些条形码扫描器在每个 String 读和/或新行字符的末尾插入回车。 要改正这个问题并使代码可用于所有条形码,我们创建了大于条形码长度的缓冲区,并且在创建 String 时只使用我们感兴趣的字符。从本质上讲,这将忽略一些条形码最终所具有的无关字符。
    	barCodeString = new String(buffer, 0, length);

最后,当读取和转换条形码时,我们必须通知所有侦听器有关新 String 的信息。 但是,在侦听器的所有 barCodeScanned() 方法中循环很费时,尤其当它们查询数据库时(正如它在本案例中所做的)。 在 Java 抽象窗口工具包(Java Abstract Window Toolkit,AWT)模型中,如果还没有完成第一个事件的 actionPerformed() , 那么单击按钮两次将不会发出两个 ActionEvent。 这对于条形码扫描器来说是无法接受的,因为当快速读取条形码时,我们不能允许丢失它们。 因此,我们必须为每个条形码读取产生一个新线程, 使该线程调用并等待 AWT 线程,确保在发生“象机关枪扫射一样连续快速扫描”时不会丢失条形码。

为每个条形码读取创建新线程有其消极方面 ― 常见的线程问题产生了其消极的一面: 锁定、监视器、争用条件以及在凌晨 2 点完成大学里 OS 课程的程序之前尝试忽略的所有事情。 但是我们扯开一下……虽然演示应用程序不处理这些问题,因为用户在应用程序(如收款处)中不对条形码“象机关枪扫射一样连续快速扫描”, 所以可以通过使用线程安全的队列和同步块来解决它们。

GUI

虽然不是以应用程序为中心,但简单的 GUI 让您了解了应用程序如何使用条形码扫描器。 它是使用模型-视图-控制器(Model-View-Controller (MVC))设计来设置的。 启动 J*Mart 应用程序的 main 方法也在 InventoryView 类中。

模型

InventoryData 在该应用程序中充当模型。它是一种简单的 JavaBean, 包含需要从 View 传递到数据库的所有数据。

视图

InventoryView 显示运行该应用程序所需的所有信息, 并处理某些方案:

  • 读取数据库中不存在的条形码。然后,应用程序将让用户输入名称、价格和数量,以插入数据库中。
    数据库中不存在条形码
    数据库中不存在条形码
  • 读取 DB 中 确实 存在的条形码。它将显示该信息,然后让用户添加一定数量的库存, 删除一定数量的库存或从 DB 中删除整个产品。
    数据库中存在条形码
    数据库中存在条形码

在这些方案中,应用程序让用户完全控制以空表开始的 DB 中的库存。

控制器

InventoryController 充当 DatabaseAccess 类的网关,处理 BarCodeScanner 并将信息传递到 InventoryView 以供显示。

结束语

这个小应用程序的目的是显示如何开发一个有效的框架来使用条形码,并且通过将条形码中提供的信息用做搜索键来检索数据库中的信息。虽然这个应用程序是为 UPC 符号定制的,但只要在特性设置中做一些更改,BarCodeScanner 的代码就可完全重用于市场上的任何条形码设置和每种条形码扫描器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VB语言可以通过调用第三方库或者使用内置的类库实现读取条形码的功能。 一种常见的方法是使用第三方库,例如Zxing(Zebra Crossing)库。Zxing是一个功能强大的开源条形码图像处理库,支持多种类型的条形码,包括一维码和二维码等。 在VB中使用Zxing库,首先需要下载并添加对应的Zxing库文件到项目中。接下来,可以通过以下代码实现对图片中的条形码进行识别和解码: ``` Imports ZXing Private Sub ReadBarcode(imagePath As String) ' 创建BarcodeReader对象 Dim reader As New BarcodeReader ' 设置解码类型 reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {BarcodeFormat.CODE_128} ' 读取图片 Dim bmp As New Bitmap(imagePath) ' 解码条形码 Dim result As Result = reader.Decode(bmp) ' 判断是否成功解码 If result IsNot Nothing Then ' 输出解码结果 MsgBox(result.Text) Else MsgBox("未能识别到条形码") End If ' 释放资源 reader = Nothing bmp.Dispose() End Sub ``` 以上代码中,首先创建了一个BarcodeReader对象,并通过设置Options属性来指定解码类型,例如CODE_128类型的条形码。接下来,通过Bitmap类加载待识别的图片,然后调用Decode方法进行解码。最后判断解码结果是否为空,并输出解码结果或者提示未能识别到条形码。 需要注意的是,Zxing库不仅支持VB,还支持多种编程语言,因此可以很方便地在不同的开发环境中使用。同时,在使用第三方库时,需要确保库文件与项目的版本兼容并正确引用。 另外,也可以探索VB内置的条形码类库,例如Microsoft.VisualBasic.Compatibility.VB6命名空间下的编码和解码函数。具体的实现方式可以查阅VB的官方文档或者相关教程。 ### 回答2: VB图片读取条形码的源码主要包含以下几个部分。 第一部分是导入所需要的命名空间和引用。我们需要引用`System.Drawing`命名空间,它包含了处理图像的各种类、方法和属性。 第二部分是定义函数的代码。在函数中,我们需要先将图片加载到内存中,并利用`Bitmap`类将其转换为位图。然后,使用`BarcodeReader`类中的`Read`方法来读取条形码。最后,通过返回读取到的条形码值来输出结果。 下面是一个示意的VB图片读取条形码的源码: ```vb Imports System.Drawing Imports ZXing Public Class BarcodeReaderVB Public Function ReadBarcodeFromImage(imagePath As String) As String Dim barcodeReader As New BarcodeReader() Dim image As New Bitmap(imagePath) Dim result As Result = barcodeReader.Read(image) Return result.Text End Function End Class ``` 在上述代码中,通过`Imports`语句导入了`System.Drawing`和`ZXing`命名空间。`BarcodeReaderVB`类中的`ReadBarcodeFromImage`函数接受一个图片路径作为参数,并返回读取到的条形码值。 使用该源码时,只需创建`BarcodeReaderVB`类的实例,然后调用`ReadBarcodeFromImage`函数,并将待读取的图片路径作为参数传入即可。 需要注意的是,这只是一个简单的示例,真实的应用中可能还需要处理一些异常情况,比如图片不存在或无法读取条形码等。同时,该源码基于ZXing库,你需要导入相应的库文件供程序使用。 希望以上的回答能对你有所帮助,如有问题请随时追问。 ### 回答3: 根据题目要求,应该是要用VB语言编写一个程序来读取条形码的源代码。 首先,我们需要利用VB的一些图形处理函数来读取图片文件。可以使用以下代码读取一张图片: ``` Dim bmp As New Bitmap("图片路径") ``` 接下来,我们需要引用一些第三方的条形码识别库来实现条形码的识别功能。比如,可以使用ZBar这个开源的条形码识别库。 首先,需要下载ZBar的VB.NET版本的库文件,并将其引入项目中。 然后,可以使用以下代码来实现条形码的识别: ``` Dim scanner As New ZBar.ImageScanner() scanner.SetConfiguration(ZBar.SymbolType.CODE128, ZBar.Config.Enabled, 1) Dim source As ZBar.Image = New ZBar.Image(bmp, bmp.Width, bmp.Height, ZBar.ImageFormat.RGBA) Dim resultCount As Integer = scanner.Scan(source) For Each symbol As ZBar.Symbol In source ' 输出条形码的内容 Console.WriteLine(symbol.Data) Next ' 释放资源 source.Dispose() ``` 这段代码中,我们首先创建了一个ZBar的图像扫描器对象,然后设置了条形码的类型为CODE128,接着创建了一个ZBar的图像对象,并将读取到的图片传入。然后通过调用扫描器的Scan方法,扫描图像中的条形码,并将结果存储在symbol中。最后,我们可以通过遍历symbol的Data属性获取到条形码的内容。 以上就是使用VB语言读取条形码的源代码。当然,因为条形码的识别库不同,具体实现会有所差异,但大致的思路和框架是相似的。希望这些信息对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值