网文笔名:条码基础知识及开发简介

来源:百度文库 编辑:中财网 时间:2024/04/30 14:19:58
 

条码基础知识及开发简介

 

 

条码的基础知识

条码是指由一组规则排列的条、空及对应字符组成的标识,用以表示一定的商品信息的符号。

目前世界上常用的码制有ENA条形码、UPC条形码、25条形码、交叉25五条形码、库德巴条形码、39条形码和128条形码等,而商品上最常使用的就是EAN商品条形码。

条形码技术是在计算机技术与信息技术基础上发展起来的一门集编码、印刷、识别、数据采集和处理于一身的新兴技术,主要解决物品的自动识别问题。

条形码技术应用的主要特点:

1、 高速:键盘输入12位数字需要6秒,而用条形码扫描器输入只要0.2秒。

2、 准确:条形码的正确识读率达99.99%-----99.999%。

3、 成本低:自动识别技术中,条形码标签成本低,识读设备价格便宜。

4、 灵活:根据顾客或业务的需求,容易开发出 新产品,输入、输出设备种类多,操作简便。

条形码应用范围

1 商业领域 

2 CODE 39码在管理领域应用较多

3 ITF 25码在物流领域应用较多

4 Codebar码多用在医疗、图书领域

5 生产企业工厂

条码分类

1、按码制分类

1) UPC码

1973年,美国率先在国内的商业系统中应用于UPC码之后加拿大也在商业系统中采用UPC码。UPC码是一种长度固定的连续型数字式码制,其字符集为数字0~9。它采用四种元素宽度,每个条或空是1、2、3或4倍单位元素宽度。IPC码有两种类型,即UPC-A码和UPC-E码。

2) EAN码

1977年,欧洲经济共同体各国按照UPC码的标准制定了欧洲物品编码EAN码,与UPC码兼容,而且两者具有相同的符号体系。EAN码的字符编号结构与UPC码相同,也是长度固定的、连续型的数字式码制,其字符集是数字0~9。它采用四种元素宽度,每个条或空是1、2、3或4倍单位元素宽度。EAN码有两种类型,即EAN-13码和EAN-8码

3)交叉25码

交叉25码是一种长度可变的连续型自校验数字式码制,其字符集为数字0~9。采用两种元素宽度,每个条和空是宽或窄元素。编码字符个数为偶数,所有奇数位置上的数据以条编码,偶数位置上的数据以空编码。如果为奇数个数据编码,则在数据前补一位0,以使数据为偶数个数位。

4)39码

39码是第一个字母数字式码制。1974年由Intermec公司推出。它是长度可比的离散型自校险字母数字式码制。其字符集为数字0—9,26个大写字母和7特殊字符(-、。、Space、/、%、¥),共43个字符。每个字符由9个元素组成,其中有5个条(2个宽条,3个窄条)和4个空(1个宽空,3个窄空),是一种离散码。

5)库德巴码

库德巴码(Code Bar)出现于1972年,是一种长度可变的连续型自校验数字式码制。其字符集为数字0—9和6个特殊字符(-、:、/、。、+、¥),共16个字符。常用于仓库、血库和航空快递包裹中。

6)128码

128码出现于1981年,是一种长度可变的连续型自校验数字式码制。它采用四种元素宽度,每个字符由3个条和3个空,共11个单元元素宽度, 又称(11,3)码。它由106个不,同条形码字符,每个条形码字符有三种含义不同的字符集,分别为A、B、C。它使用这3个交替的字符集可将128个ASCII码编码。

7)93码

93码是一种长度可变的连续型字母数字式码制。其字符集成为数字。0-9,26个大写字母和7个特殊字符(-、。、Space、/、+、%、¥)以及4个控制字符。每个字符由3个条和3个罕,共9个元素宽度。

8)49码

49码是一种多行的连续型、长度可变的字母数字式码制。出现于1987年,主要用于小物品标签上的符号。采用多种元素宽度。其字符集为数字0-9,26个大写字母和7个特殊字符(-、。、Space、%、/、+、%、¥)、3个功能键(F1、F2、F3)和3个变换字符,共49个字符。

9)其他码制

除上述码外,还有其他的码制,例如25码出现于1977年,主要用于电子元器件标签;矩阵25码11码的变形;Nixdorf码已被EAN码所取代Plessey码出现于1971年5月主要用于图书馆等。

2、按维数分类

1)普通的一维条码

普通的一维条码自本问世以来,很快得到了普及并广泛应用。但是由于一维条码的信息容量很小,如商品上的条码仅能容13位的阿拉伯数字,更多的描述商品的信息只能依赖数据库的支持,离开了预先建立的数据库,这种条码就变成了无源之水,无本之木,因而条码的应用范围受到了一定的限制。

2)二维条码

除具有普通条码的优点外,二维条码还具有信息容量大、可靠性高、保密防伪性强、易于制作、成本低等优点。
美国Symbol公司于1991年正式推出名为PDF417的二维条码,简称为PDF417条码,即“便携式数据文件”。FDF417条码是一种高密度、高信息含量的便携式数据文件,是实现证件及卡片等大容量、高可靠性信息自动存储、携带并可用机器自动识读的理想手段。

3)多维条码

进入20世纪80年代以来,人们围绕如何提高条形码符号的信息密度,进行了研究工作。多维条形码和集装箱条形码成为研究、以展与应用的方向。信息密度是描述条形码符号的一个重要参数据,即单位长度中可能编写的字母个数,通常记作:字母个数/cm。影响信息密度的主要因素是条、空结构和窄元系的宽度。128码93码就是人们为提高密度而进行的成功的尝试。128码城1981年被推荐应用;而93码于1982年投入使用。这两种码的符号密度均比39码高将近30%。随着条形码技术的发展和条形码三制的种类不断增加,条形码的标准化显得愈来愈重要。为此,曾先后制定了军用标准1189;交叉25码39码和Coda Bar码ANSI标准MH10.8M等。同时,一些行业也开始建立行业标准,以适应发展的需要。此后,戴维·阿利尔又研制出49码。这是一种非传统的条形码符号,它比以往的条形码符号具有更高的密度。特德·威廉姆斯(Ted Williams)GFI988推出16K码,该码的结构类似于49码,是一种比较新型的码制,适用于激光系统。

条码开发

1、 不同编码规则的条形码生成

  public string bar_code(object str, int ch, int cw, int type_code)
{
    //str:输入的字符串;ch:要显示条形码的高度;cw:要显示条形码的宽度;type_code:代码类型
    string strTmp = str.ToString();
    string code = strTmp;
     // ToLower()将string转化成小写形式的副本,返回是使用指定区域的性的大小写规则。
     strTmp = strTmp.ToLower();

int height = ch;
int width = cw;

//将传入的参数进行转化。
strTmp = strTmp.Replace("0", "_|_|__||_||_|"); ;
strTmp = strTmp.Replace("1", "_||_|__|_|_||");
strTmp = strTmp.Replace("2", "_|_||__|_|_||");
strTmp = strTmp.Replace("3", "_||_||__|_|_|");
strTmp = strTmp.Replace("4", "_|_|__||_|_||");
strTmp = strTmp.Replace("5", "_||_|__||_|_|");
strTmp = strTmp.Replace("7", "_|_|__|_||_||");
strTmp = strTmp.Replace("6", "_|_||__||_|_|");
strTmp = strTmp.Replace("8", "_||_|__|_||_|");
strTmp = strTmp.Replace("9", "_|_||__|_||_|");
strTmp = strTmp.Replace("a", "_||_|_|__|_||");
strTmp = strTmp.Replace("b", "_|_||_|__|_||");
strTmp = strTmp.Replace("c", "_||_||_|__|_|");
strTmp = strTmp.Replace("d", "_|_|_||__|_||");
strTmp = strTmp.Replace("e", "_||_|_||__|_|");
strTmp = strTmp.Replace("f", "_|_||_||__|_|");
strTmp = strTmp.Replace("g", "_|_|_|__||_||");
strTmp = strTmp.Replace("h", "_||_|_|__||_|");
strTmp = strTmp.Replace("i", "_|_||_|__||_|");
strTmp = strTmp.Replace("j", "_|_|_||__||_|");
strTmp = strTmp.Replace("k", "_||_|_|_|__||");
strTmp = strTmp.Replace("l", "_|_||_|_|__||");
strTmp = strTmp.Replace("m", "_||_||_|_|__|");
strTmp = strTmp.Replace("n", "_|_|_||_|__||");
strTmp = strTmp.Replace("o", "_||_|_||_|__|");
strTmp = strTmp.Replace("p", "_|_||_||_|__|");
strTmp = strTmp.Replace("r", "_||_|_|_||__|");
strTmp = strTmp.Replace("q", "_|_|_|_||__||");
strTmp = strTmp.Replace("s", "_|_||_|_||__|");
strTmp = strTmp.Replace("t", "_|_|_||_||__|");
strTmp = strTmp.Replace("u", "_||__|_|_|_||");
strTmp = strTmp.Replace("v", "_|__||_|_|_||");
strTmp = strTmp.Replace("w", "_||__||_|_|_|");
strTmp = strTmp.Replace("x", "_|__|_||_|_||");
strTmp = strTmp.Replace("y", "_||__|_||_|_|");
strTmp = strTmp.Replace("z", "_|__||_||_|_|");
strTmp = strTmp.Replace("-", "_|__|_|_||_||");
strTmp = strTmp.Replace("*", "_|__|_||_||_|");
strTmp = strTmp.Replace("/", "_|__|__|_|__|");
strTmp = strTmp.Replace("%", "_|_|__|__|__|");
strTmp = strTmp.Replace("+", "_|__|_|__|__|");
strTmp = strTmp.Replace(".", "_||__|_|_||_|");
strTmp = strTmp.Replace("_", "");
strTmp = strTmp.Replace("|", "");

if (type_code == 1)
{
   return strTmp + "
" + code;
}
else
{
   return strTmp;
}

} 

2、 条形码打印

条码打印机分两种:(1)有驱动条码打印机(2)无驱动条码打印机。针对于不同类型的打印机有不同打印方式

(一)     有驱动条码打印机

针对于有驱条码打印机,可以直接用windows的API,指令格式是一样的只需要知道安装后的打印机名称即可。

p_PrintName 为打印机名称

 public static void WinApiPrintByte(string p_PrintName, byte[] p_Byte)
 {
        if (p_PrintName != null && p_PrintName.Length > 0)
        {
             IntPtr _PrintHandle;
              IntPtr _JobHandle = Marshal.AllocHGlobal(100);
              if (Win32API.OpenPrinter(p_PrintName, out _PrintHandle, IntPtr.Zero))
                {
                    ADDJOB_INFO_1 _JobInfo = new ADDJOB_INFO_1();
                    int _Size;
                    AddJob(_PrintHandle, 1, _JobHandle, 100, out _Size);
      _JobInfo = (ADDJOB_INFO_1)Marshal.PtrToStructure(_JobHandle, typeof(ADDJOB_INFO_1));
                    System.IO.File.WriteAllBytes(p_PrintName, p_Byte);
                    ScheduleJob(_PrintHandle, _JobInfo.JobID);
                    ClosePrinter(_PrintHandle);
                    Marshal.FreeHGlobal(_JobHandle);
                }
            }
        }

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
   public struct ADDJOB_INFO_1
    {
            [MarshalAs(UnmanagedType.LPTStr)]
            public string lpPath;
            public Int32 JobID;
    }
     [DllImport("winspool.drv", CharSet = CharSet.Auto)]
    public static extern bool AddJob(IntPtr ptrPrinter, Int32 iLevel, IntPtr ptrJob, Int32 iSize, out Int32 iCpSize);

  [DllImport("winspool.drv", CharSet = CharSet.Auto)]
     public static extern bool ScheduleJob(IntPtr ptrPrinter, Int32 JobID);

    [DllImport("winspool.drv", CharSet = CharSet.Auto)]
    public static extern bool ClosePrinter(IntPtr ptrPrinter);

(二)     无驱动条码打印机

无驱打印机主要有LPT打印机和IP打印机,该种打印机是通过ZPL指令直接给端口发指令即可

3、 条形码的读取

条形码读取的方式主要有两种:

1) 键盘口或USB口

该种接口的条码读写器,如同在键盘上按下数字键一样,基本不需任何编程和处理

2) 其他接口

如果你使用的是其它接口的话,可能你就要为该设备编写通讯代码了。
     static SerialPort _serialPort;

     public static void Main()

    {

        string name;

        string message;

        StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;

        Thread readThread = new Thread(Read);

 

        // Create a new SerialPort object with default settings.

        _serialPort = new SerialPort();

 

        // Allow the user to set the appropriate properties.

        _serialPort.PortName = SetPortName(_serialPort.PortName);

        _serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate);

        _serialPort.Parity = SetPortParity(_serialPort.Parity);

        _serialPort.DataBits = SetPortDataBits(_serialPort.DataBits);

        _serialPort.StopBits = SetPortStopBits(_serialPort.StopBits);

        _serialPort.Handshake = SetPortHandshake(_serialPort.Handshake);

 

        // Set the read/write timeouts

        _serialPort.ReadTimeout = 500;

        _serialPort.WriteTimeout = 500;

 

        _serialPort.Open();

        _continue = true;

        readThread.Start();

 

        Console.Write("Name: ");

        name = Console.ReadLine();

 

        Console.WriteLine("Type QUIT to exit");

 

        while (_continue)

        {

            message = Console.ReadLine();

 

            if (stringComparer.Equals("quit", message))

            {

                _continue = false;

            }

            else

            {

                _serialPort.WriteLine(

                    String.Format("<{0}>: {1}", name, message));

            }

        }

 

        readThread.Join();

        _serialPort.Close();

    }

 

    public static void Read()

    {

        while (_continue)

        {

            try

            {

                string message = _serialPort.ReadLine();

                Console.WriteLine(message);

            }

            catch (TimeoutException) { }

        }

    }