C#条形码生成(六)----GS1-128条形码

首先需要说明该部分代码虽然经过个人测试,也使用扫描枪测试,但本人不保证代码完全正确

其次代码没有遵循“先预定义长度后非定长”的原则,但遵循了非预定义长度字符串后都加入FNC1分隔符

最后虽然此部分代码遵循了 GBT 16986-2009 商品条码 应用标识符标准,但实际并未完全遵循,仅遵循了标识符长度和输入字母原则

补充:此部分代码用到了前面的Code128Auto的生成编码代码,所以将部分代码做了调整,以下是相关的代码

Code128

/// <summary>
    /// Code128基础相关类
    /// </summary>
    internal static class Code128
    {
        /*
             *  128  尺寸要求
             *  最小模块宽度 x  最大1.016mm,最小0.250mm 一个系统中的x应为一恒定值  标准是1mm,放大系数0.25~1.2
             *  左右侧空白区最小宽度为 10x
             *  条高通常为32mm,实际可以根据具体要求
             *  
             * 最大物理长度不应超过 165mm,可编码的最大数据字符数为48,其中包括应用标识符和作为分隔符使用的FNC1字符,但不包括辅助字符和校验符
             * 
             * AI中FNC1同样作为分隔符使用
             * 
             * ASCII
             * 0~31 StartA  专有
             * 96~127 StartB 专有
         * 
         * EAN128不使用空格(ASCII码32)
        */

        /// <summary>
        /// Code128条空排列集合,1代表条b,0代表空s,Index对应符号字符值S
        /// </summary>
        internal static readonly List<string> BSList = new List<string>()
        {
                "212222" , "222122" , "222221" , "121223" , "121322" , "131222" , "122213" , "122312" , "132212" , "221213" ,
                "221312" , "231212" , "112232" , "122132" , "122231" , "113222" , "123122" , "123221" , "223211" , "221132" ,
                "221231" , "213212" , "223112" , "312131" , "311222" , "321122" , "321221" , "312212" , "322112" , "322211" ,
                "212123" , "212321" , "232121" , "111323" , "131123" , "131321" , "112313" , "132113" , "132311" , "211313" ,
                "231113" , "231311" , "112133" , "112331" , "132131" , "113123" , "113321" , "133121" , "313121" , "211331" ,
                "231131" , "213113" , "213311" , "213131" , "311123" , "311321" , "331121" , "312113" , "312311" , "332111" ,
                "314111" , "221411" , "431111" , "111224" , "111422" , "121124" , "121421" , "141122" , "141221" , "112214" ,
                "112412" , "122114" , "122411" , "142112" , "142211" , "241211" , "221114" , "413111" , "241112" , "134111" ,
                "111242" , "121142" , "121241" , "114212" , "124112" , "124211" , "411212" , "421112" , "421211" , "212141" ,
                "214121" , "412121" , "111143" , "111341" , "131141" , "114113" , "114311" , "411113" , "411311" , "113141" ,
                "114131" , "311141" , "411131" , "211412" , "211214" , "211232" , "2331112"
        };

        #region 条空排列集合
        //{
            //    "11011001100" , "11001101100" , "11001100110" , "10010011000" , "10010001100" ,
            //    "10001001100" , "10011001000" , "10011000100" , "10001100100" , "11001001000" ,
            //    "11001000100" , "11000100100" , "10110011100" , "10011011100" , "10011001110" ,
            //    "10111001100" , "10011101100" , "10011100110" , "11001110010" , "11001011100" ,
            //    "11001001110" , "11011100100" , "11001110100" , "11101101110" , "11101001100" ,
            //    "11100101100" , "11100100110" , "11101100100" , "11100110100" , "11100110010" ,
            //    "11011011000" , "11011000110" , "11000110110" , "10100011000" , "10001011000" ,
            //    "10001000110" , "10110001000" , "10001101000" , "10001100010" , "11010001000" ,
            //    "11000101000" , "11000100010" , "10110111000" , "10110001110" , "10001101110" ,
            //    "10111011000" , "10111000110" , "10001110110" , "11101110110" , "11010001110" ,
            //    "11000101110" , "11011101000" , "11011100010" , "11011101110" , "11101011000" ,
            //    "11101000110" , "11100010110" , "11101101000" , "11101100010" , "11100011010" ,
            //    "11101111010" , "11001000010" , "11110001010" , "10100110000" , "10100001100" ,
            //    "10010110000" , "10010000110" , "10000101100" , "10000100110" , "10110010000" ,
            //    "10110000100" , "10011010000" , "10011000010" , "10000110100" , "10000110010" ,
            //    "11000010010" , "11001010000" , "11110111010" , "11000010100" , "10001111010" ,
            //    "10100111100" , "10010111100" , "10010011110" , "10111100100" , "10011110100" ,
            //    "10011110010" , "11110100100" , "11110010100" , "11110010010" , "11011011110" ,
            //    "11011110110" , "11110110110" , "10101111000" , "10100011110" , "10001011110" ,
            //    "10111101000" , "10111100010" , "11110101000" , "11110100010" , "10111011110" ,
            //    "10111101110" , "11101011110" , "11110101110" , "11010000100" , "11010010000" ,
            //    "11010011100" , "1100011101011"
        //};
        #endregion

        internal const byte FNC3_AB = 96, FNC2_AB = 97, SHIFT_AB = 98, CODEC_AB = 99, CODEB_AC = 100, CODEA_BC = 101;

        internal const byte FNC4_A = 101, FNC4_B = 100;

        internal const byte FNC1 = 102, StartA = 103, StartB = 104, StartC = 105;
        internal const byte Stop = 106;



        /// <summary>
        /// 获取字符在字符集A中对应的符号字符值S
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        internal static byte GetSIndexFromA(char c)
        {
            byte sIndex = (byte)c;
            //字符集A中 符号字符值S 若ASCII<32,则 S=ASCII+64 ,若95>=ASCII>=32,则S=ASCII-32
            if (sIndex < 32)
            {
                sIndex += 64;
            }
            else if (sIndex < 96)
            {
                sIndex -= 32;
            }
            else
            {
                throw new NotImplementedException();
            }
            return sIndex;
        }
        /// <summary>
        /// 获取字符在字符集B中对应的符号字符值S
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        internal static byte GetSIndexFromB(char c)
        {
            byte sIndex = (byte)c;
            if (sIndex > 31 && sIndex < 128)
            {
                sIndex -= 32;//字符集B中ASCII码 减去32后就等于符号字符值
            }
            else
            {
                throw new NotImplementedException();
            }
            return sIndex;
        }
        internal static byte GetSIndex(CharacterSet characterSet, char c)
        {
            switch (characterSet)
            {
                case CharacterSet.A:
                    return GetSIndexFromA(c);
                case CharacterSet.B:
                    return GetSIndexFromB(c);
                default:
                    throw new NotImplementedException();
            }
        }
        /// <summary>
        /// 判断指定字符是否仅属于指定字符集
        /// </summary>
        /// <param name="characterSet"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        internal static bool CharOnlyBelongsTo(CharacterSet characterSet, char c)
        {
            switch (characterSet)
            {
                case CharacterSet.A:
                    return (byte)c < 32;
                case CharacterSet.B:
                    return (byte)c > 95 && (byte)c < 128;
                default:
                    throw new NotImplementedException();
            }
        }
        /// <summary>
        /// 判断指定字符是否不属于指定字符集
        /// </summary>
        /// <param name="characterSet"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        internal static bool CharNotBelongsTo(CharacterSet characterSet, char c)
        {
            switch (characterSet)
            {
                case CharacterSet.A:
                    return (byte)c > 95;
                case CharacterSet.B:
                    return (byte)c < 32 && (byte)c > 127;
                default:
                    throw new NotImplementedException();
            }
        }
        /// <summary>
        /// 当编码转换时,获取相应的切换符对应的符号字符值
        /// </summary>
        /// <param name="newCharacterSet"></param>
        /// <returns></returns>
        internal static byte GetCodeXIndex(CharacterSet newCharacterSet)
        {
            switch (newCharacterSet)
            {
                case CharacterSet.A:
                    return CODEA_BC;
                case CharacterSet.B:
                    return CODEB_AC;
                default:
                    return CODEC_AB;
            }
        }
        /// <summary>
        /// 获取转换后的字符集
        /// </summary>
        /// <param name="characterSet"></param>
        /// <returns></returns>
        internal static CharacterSet GetShiftCharacterSet(CharacterSet characterSet)
        {
            switch (characterSet)
            {
                case CharacterSet.A:
                    return CharacterSet.B;
                case CharacterSet.B:
                    return CharacterSet.A;
                default:
                    throw new NotImplementedException();
            }
        }
        /// <summary>
        /// 获取指定字符串应该采用的起始符对应的符号字符值
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        internal static byte GetStartIndex(string data, out CharacterSet startCharacterSet)
        {
            startCharacterSet = GetCharacterSet(data, 0);
            switch (startCharacterSet)
            {
                case CharacterSet.A:
                    return StartA;
                case CharacterSet.B:
                    return StartB;
                default:
                    return StartC;
            }
        }
        /// <summary>
        /// 获取应采用的字符集
        /// </summary>
        /// <param name="data"></param>
        /// <param name="startIndex">判断开始位置</param>
        /// <returns></returns>
        internal static CharacterSet GetCharacterSet(string data, int startIndex)
        {
            CharacterSet returnSet = CharacterSet.B;
            if (Regex.IsMatch(data.Substring(startIndex), @"^\d{4,}"))
            {
                returnSet = CharacterSet.C;
            }
            else
            {
                byte byteC = GetProprietaryChar(data, startIndex);
                returnSet = byteC < 32 ? CharacterSet.A : CharacterSet.B;
            }
            return returnSet;
        }
        /// <summary>
        /// 从指定位置开始,返回第一个大于95(并且小于128)或小于32的字符对应的值
        /// </summary>
        /// <param name="data"></param>
        /// <param name="startIndex"></param>
        /// <returns>如果没有任何字符匹配,则返回255</returns>
        internal static byte GetProprietaryChar(string data, int startIndex)
        {
            byte returnByte = byte.MaxValue;
            for (int i = startIndex; i < data.Length; i++)
            {
                byte byteC = (byte)data[i];
                if (byteC < 32 || byteC > 95 && byteC < 128)
                {
                    returnByte = byteC;
                    break;
                }
            }
            return returnByte;
        }
        /// <summary>
        /// 获取字符串从指定位置开始连续出现数字的个数
        /// </summary>
        /// <param name="data"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        internal static int GetDigitLength(string data, int startIndex)
        {
            int digitLength = data.Length - startIndex;//默认设定从起始位置开始至最后都是数字
            for (int i = startIndex; i < data.Length; i++)
            {
                if (!char.IsDigit(data[i]))
                {
                    digitLength = i - startIndex;
                    break;
                }
            }
            return digitLength;
        }

        /// <summary>
        /// 通用方法
        /// </summary>
        /// <param name="tempBuilder"></param>
        /// <param name="sIndex"></param>
        /// <param name="nowWeight"></param>
        /// <param name="checkNum"></param>
        internal static void EncodingCommon(StringBuilder tempBuilder, byte sIndex, ref int nowWeight, ref int checkNum)
        {
            tempBuilder.Append(BSList[sIndex]);
            checkNum += nowWeight * sIndex;
            nowWeight++;
        }
        /// <summary>
        /// 获取原始数据对应的编码后数据(不包括起始符、特殊符(EAN128时)、检验符、终止符)
        /// </summary>
        /// <param name="rawData">编码对应的原始数据</param>
        /// <param name="tempBuilder">编码数据容器</param>
        /// <param name="nowCharacterSet">当前字符集</param>
        /// <param name="i">字符串索引</param>
        /// <param name="nowWeight">当前权值</param>
        /// <param name="checkNum">当前检验值总和</param>
        internal static void GetEncodedData(string rawData, StringBuilder tempBuilder, ref CharacterSet nowCharacterSet, ref int i, ref int nowWeight, ref int checkNum)
        {//因为可能存在字符集C,所以i与nowWeight可能存在不一致关系,所以要分别定义
            byte sIndex;
            switch (nowCharacterSet)
            {
                case CharacterSet.A:
                case CharacterSet.B:
                    for (; i < rawData.Length; i++)
                    {
                        if (char.IsDigit(rawData[i]))
                        {
                            //数字
                            int digitLength = GetDigitLength(rawData, i);
                            if (digitLength >= 4)
                            {
                                //转入CodeC
                                if (digitLength % 2 != 0)
                                {//奇数位数字,在第一个数字之后插入CodeC字符
                                    sIndex = GetSIndex(nowCharacterSet, (rawData[i]));
                                    EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                                    i++;
                                }
                                nowCharacterSet = CharacterSet.C;
                                sIndex = GetCodeXIndex(nowCharacterSet);//插入CodeC切换字符
                                EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                                GetEncodedData(rawData, tempBuilder, ref nowCharacterSet, ref i, ref nowWeight, ref checkNum);
                                return;
                            }
                            else
                            {
                                //如果小于4位数字,则直接内部循环结束
                                for (int j = 0; j < digitLength; j++)
                                {
                                    sIndex = GetSIndex(nowCharacterSet, (rawData[i]));
                                    EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                                    i++;
                                }
                                i--;//因为上面循环结束后继续外部循环会导致i多加了1,所以要减去1
                                continue;
                            }
                        }
                        else if (CharNotBelongsTo(nowCharacterSet, rawData[i]))
                        {//当前字符不属于目前的字符集
                            byte tempByte = GetProprietaryChar(rawData, i + 1);//获取当前字符后第一个属于A,或B的字符集
                            CharacterSet tempCharacterSet = GetShiftCharacterSet(nowCharacterSet);
                            if (tempByte != byte.MaxValue && CharOnlyBelongsTo(nowCharacterSet, (char)tempByte))
                            {
                                //加入转换符
                                sIndex = SHIFT_AB;
                                EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);

                                sIndex = GetSIndex(tempCharacterSet, rawData[i]);
                                EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                                continue;
                            }
                            else
                            {
                                //加入切换符
                                nowCharacterSet = tempCharacterSet;
                                sIndex = GetCodeXIndex(nowCharacterSet);
                                EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                                GetEncodedData(rawData, tempBuilder, ref nowCharacterSet, ref i, ref nowWeight, ref checkNum);
                                return;
                            }
                        }
                        else
                        {
                            sIndex = GetSIndex(nowCharacterSet, rawData[i]);
                            EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                        }
                    }
                    break;
                default:
                    for (; i < rawData.Length; i += 2)
                    {
                        if (i != rawData.Length - 1 && char.IsDigit(rawData, i) && char.IsDigit(rawData, i + 1))
                        {
                            sIndex = byte.Parse(rawData.Substring(i, 2));
                            EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                        }
                        else
                        {
                            nowCharacterSet = GetCharacterSet(rawData, i);
                            //插入转换字符
                            sIndex = GetCodeXIndex(nowCharacterSet);
                            EncodingCommon(tempBuilder, sIndex, ref nowWeight, ref checkNum);
                            GetEncodedData(rawData, tempBuilder, ref nowCharacterSet, ref i, ref nowWeight, ref checkNum);
                            return;
                        }
                    }
                    break;
            }
        }
    }

    /// <summary>
    /// Code128字符集
    /// </summary>
    internal enum CharacterSet
    {
        A,
        B,
        C
    }


AI相关

/// <summary>
    /// 商品应用标识符标准 GBT 16986-2009 
    /// </summary>
    internal static class AI
    {
        /// <summary>
        /// GBT 16986-2009 定义的应用标识符集合
        /// </summary>
        public static readonly List<ApplicationIdentifier> AIList = new List<ApplicationIdentifier>()
        {
            //20系列货运包装箱代码
            new ApplicationIdentifier("00", new List<DataFormat>(){ new DataFormat(new byte[]{18})}),
            //01全球贸易项目代码
            new ApplicationIdentifier("01", new List<DataFormat>(){ new DataFormat(new byte[]{14})}),
            //02物流单元内贸易项目的GTIN
            new ApplicationIdentifier("02", new List<DataFormat>(){ new DataFormat(new byte[]{14})}),
            //10批号
            new ApplicationIdentifier("10", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,20})}),
            //11生产日期YYMMDD
            new ApplicationIdentifier("11", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //12付款截止日期YYMMDD
            new ApplicationIdentifier("12", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //13包装日期YYMMDD
            new ApplicationIdentifier("13", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //15保质期YYMMDD
            new ApplicationIdentifier("15", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //17有效期YYMMDD
            new ApplicationIdentifier("17", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //20产品变体
            new ApplicationIdentifier("20", new List<DataFormat>(){ new DataFormat(new byte[]{2})}),
            //21系列号
            new ApplicationIdentifier("21", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,20})}),
            //22医疗卫生行业产品二级数据
            new ApplicationIdentifier("22", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,29})}),
            //240附加产品标识
            new ApplicationIdentifier("240", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //241客户方代码
            new ApplicationIdentifier("241", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //242定制产品代码
            new ApplicationIdentifier("242", new List<DataFormat>(){ new DataFormat(new byte[]{1,6})}),
            //250二级系列号
            new ApplicationIdentifier("250", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //251源实体参考代码
            new ApplicationIdentifier("251", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //253全球文件/单证类型代码
            new ApplicationIdentifier("253", new List<DataFormat>(){ new DataFormat(new byte[]{13}),new DataFormat(new byte[]{1,17})}),
            //254GLN扩展部分代码
            new ApplicationIdentifier("254", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,20})}),
            //30可变数量
            new ApplicationIdentifier("30", new List<DataFormat>(){ new DataFormat(new byte[]{1,8})}),
            //31nn 贸易与物流量度
            new ApplicationIdentifier("31", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //32nn 贸易与物流量度
            new ApplicationIdentifier("32", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //33nn 贸易与物流量度
            new ApplicationIdentifier("33", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //34nn 贸易与物流量度
            new ApplicationIdentifier("34", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //35nn 贸易与物流量度
            new ApplicationIdentifier("35", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //36nn 贸易与物流量度
            new ApplicationIdentifier("36", 4, new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //37物流单元内贸易项目数量
            new ApplicationIdentifier("37", new List<DataFormat>(){ new DataFormat(new byte[]{1,8})}),
            //390n单一货币区内应付款金额
            new ApplicationIdentifier("390", 4, new List<DataFormat>(){ new DataFormat(new byte[]{1,15})}),
            //391n具有ISO货币代码的应付款金额
            new ApplicationIdentifier("391", 4, new List<DataFormat>(){ new DataFormat(new byte[]{3}),new DataFormat(new byte[]{1,15})}),
            //392n单一货币区内变量贸易项目应付款金额
            new ApplicationIdentifier("392", 4, new List<DataFormat>(){ new DataFormat(new byte[]{1,15})}),
            //393n具有ISO货币代码的变量贸易项目应付款金额
            new ApplicationIdentifier("393", 4, new List<DataFormat>(){ new DataFormat(new byte[]{3}),new DataFormat(new byte[]{1,15})}),
            //400客户订购单代码
            new ApplicationIdentifier("400", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //401货物托运代码
            new ApplicationIdentifier("401", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //402 装运标识代码
            new ApplicationIdentifier("402", new List<DataFormat>(){ new DataFormat(new byte[]{17})}),
            //403路径代码
            new ApplicationIdentifier("403", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //410 交货地全球位置码
            new ApplicationIdentifier("410", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //411 受票方全球位置码
            new ApplicationIdentifier("411", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //412 最终目的地全球位置码
            new ApplicationIdentifier("412", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //413 交货地全球位置码
            new ApplicationIdentifier("413", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //414 标志物理位置的全球位置码
            new ApplicationIdentifier("414", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //415 开票方全球位置码
            new ApplicationIdentifier("415", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //420 同一邮政行政区域内交货地邮政编码
            new ApplicationIdentifier("420", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //421 具有3位ISO国家(或地区)代码的交货地邮政编码
            new ApplicationIdentifier("421", new List<DataFormat>(){ new DataFormat(new byte[]{3}),new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,9})}),
            //422 贸易项目原产国(或地区)
            new ApplicationIdentifier("422", new List<DataFormat>(){ new DataFormat(new byte[]{3})}),
            //423 贸易项目初始加工国(或地区)
            new ApplicationIdentifier("423", new List<DataFormat>(){ new DataFormat(new byte[]{3}),new DataFormat(new byte[]{1,12})}),
            //424 贸易项目加工国(或地区)
            new ApplicationIdentifier("424", new List<DataFormat>(){ new DataFormat(new byte[]{3})}),
            //425 贸易项目拆分国(或地区)
            new ApplicationIdentifier("425", new List<DataFormat>(){ new DataFormat(new byte[]{3})}),
            //426 全程加工贸易项目的国家(或地区)
            new ApplicationIdentifier("426", new List<DataFormat>(){ new DataFormat(new byte[]{3})}),
            //7001 北约物资代码
            new ApplicationIdentifier("7001", new List<DataFormat>(){ new DataFormat(new byte[]{13})}),
            //7002 UN/ECE胴体肉与分割品分类
            new ApplicationIdentifier("7002", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //7003 产品的有效日期和时间
            new ApplicationIdentifier("7003", new List<DataFormat>(){ new DataFormat(new byte[]{8}),new DataFormat(new byte[]{1,2})}),
            //703s 具有3位ISO国家(或地区)代码的加工者核准号码
            new ApplicationIdentifier("703", new List<DataFormat>(){ new DataFormat(new byte[]{3}),new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,27})}),
            //8001 卷装产品
            new ApplicationIdentifier("8001", new List<DataFormat>(){ new DataFormat(new byte[]{14})}),
            //8002 蜂窝移动电话标识符
            new ApplicationIdentifier("8002", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,20})}),
            //8003 全球可回收资产标识符
            new ApplicationIdentifier("8003", new List<DataFormat>(){ new DataFormat(new byte[]{14}),new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,16})}),
            //8004 全球单个资产标识符
            new ApplicationIdentifier("8004", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //8005 单价
            new ApplicationIdentifier("8005", new List<DataFormat>(){ new DataFormat(new byte[]{6})}),
            //8006 贸易项目组件的标识符
            new ApplicationIdentifier("8006", new List<DataFormat>(){ new DataFormat(new byte[]{14}),new DataFormat(new byte[]{2}),new DataFormat(new byte[]{2})}),
            //8007 国际银行账号代码
            new ApplicationIdentifier("8007", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //8008 产品生产的日期和时间
            new ApplicationIdentifier("8008", new List<DataFormat>(){ new DataFormat(new byte[]{8}),new DataFormat(new byte[]{1,4})}),
            //8018 全球服务关系代码
            new ApplicationIdentifier("8018", new List<DataFormat>(){ new DataFormat(new byte[]{18})}),
            //8020 付款单代码
            new ApplicationIdentifier("8020", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,25})}),
            //8100 GS1-128优惠券扩展代码-NSC+Offer Code
            new ApplicationIdentifier("8100", new List<DataFormat>(){ new DataFormat(new byte[]{1}),new DataFormat(new byte[]{5})}),
            //8101 GS1-128优惠券扩展代码-NSC+Offer Code + end of offer code
            new ApplicationIdentifier("8101", new List<DataFormat>(){ new DataFormat(new byte[]{1}),new DataFormat(new byte[]{5}),new DataFormat(new byte[]{4})}),
            //8102 GS1-128优惠券扩展代码-NSC
            new ApplicationIdentifier("8102", new List<DataFormat>(){ new DataFormat(new byte[]{1}),new DataFormat(new byte[]{1})}),
            //90 贸易伙伴之间相互约定的信息
            new ApplicationIdentifier("90", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //91 公司内部信息
            new ApplicationIdentifier("91", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //92 公司内部信息
            new ApplicationIdentifier("92", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //93 公司内部信息
            new ApplicationIdentifier("93", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //94 公司内部信息
            new ApplicationIdentifier("94", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //95 公司内部信息
            new ApplicationIdentifier("95", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //96 公司内部信息
            new ApplicationIdentifier("96", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //97 公司内部信息
            new ApplicationIdentifier("97", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //98 公司内部信息
            new ApplicationIdentifier("98", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})}),
            //99 公司内部信息
            new ApplicationIdentifier("99", new List<DataFormat>(){ new DataFormat(AICharacter.a| AICharacter.n, new byte[]{1,30})})
        };
        /// <summary>
        /// 需要遵循的预定义长度的应用标识符及其对应的总长度
        /// </summary>
        public static readonly List<KeyValuePair<string, byte>> PredefinedAILength = new List<KeyValuePair<string, byte>>()
        {
            new KeyValuePair<string,byte>("00",20),new KeyValuePair<string,byte>("01",16),new KeyValuePair<string,byte>("02",16),new KeyValuePair<string,byte>("03",16),
            new KeyValuePair<string,byte>("04",18),new KeyValuePair<string,byte>("11",8),new KeyValuePair<string,byte>("12",8),new KeyValuePair<string,byte>("13",8),
            new KeyValuePair<string,byte>("14",8),new KeyValuePair<string,byte>("15",8),new KeyValuePair<string,byte>("16",8),new KeyValuePair<string,byte>("17",8),
            new KeyValuePair<string,byte>("18",8),new KeyValuePair<string,byte>("19",8),new KeyValuePair<string,byte>("20",4),new KeyValuePair<string,byte>("31",10),
            new KeyValuePair<string,byte>("32",10),new KeyValuePair<string,byte>("33",10),new KeyValuePair<string,byte>("34",10),new KeyValuePair<string,byte>("35",10),
            new KeyValuePair<string,byte>("36",10),new KeyValuePair<string,byte>("41",16)

        };


        /// <summary>
        /// 获取字符串对应的 第一个 商品应用标识
        /// </summary>
        /// <param name="rawData"></param>
        /// <returns></returns>
        internal static ApplicationIdentifier GetAI(string rawData)
        {
            return AIList.Where(ai => rawData.StartsWith(ai.AI)).FirstOrDefault();
        }
        /// <summary>
        /// 判断指定字符串是否是预定义长度应用标识符
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        internal static bool IsPredefinedAI(string data)
        {
            KeyValuePair<string, byte> temp = PredefinedAILength.Where(ai => data.StartsWith(ai.Key) && data.Length == ai.Value).FirstOrDefault();
            return !string.IsNullOrEmpty(temp.Key);
        }
        /// <summary>
        /// 判断指定字符串是否是符合指定应用标识规范
        /// </summary>
        /// <param name="ai"></param>
        /// <param name="aiStr"></param>
        /// <returns></returns>
        internal static bool IsRight(ApplicationIdentifier ai, string aiStr)
        {
            //标识符部分,字符串必须以相同的AI开头
            if (!aiStr.StartsWith(ai.AI) || aiStr.Length > ai.MaxLength || aiStr.Length < ai.MinLength)
            {
                return false;
            }
            //如果AILength与ai对应的AI长度不一致时,还需检验后续几个字符是否是数字
            for (int i = ai.AI.Length; i < ai.AILength; i++)
            {
                if (!char.IsDigit(aiStr[i]))
                {
                    return false;
                }
            }

            int ptr = ai.AILength;
            for (int i = 0; i < ai.DataWithoutAI.Count; i++)
            {
                DataFormat df = ai.DataWithoutAI[i];
                for (int j = 0; j < df.Length[df.Length.Length - 1]; j++)
                {
                    if ((df.Character == AICharacter.n && !char.IsDigit(aiStr[ptr])) || (byte)aiStr[ptr] < 33 || (byte)aiStr[ptr] > 126)
                    {
                        return false;
                    }

                    ptr++;
                    if (ptr >= aiStr.Length)
                    {
                        break;
                    }
                }
            }

            return true;
        }
    }
    /// <summary>
    /// 商品标识符的数据类型范围
    /// </summary>
    [Flags]
    internal enum AICharacter
    {
        /// <summary>
        /// 数字
        /// </summary>
        n = 1,
        /// <summary>
        /// 字母
        /// </summary>
        a = 2
    }
    /// <summary>
    /// 商品应用标识
    /// </summary>
    internal sealed class ApplicationIdentifier
    {
        private bool _isFixedLength;
        private string _ai;
        private byte _aiLength;
        private List<DataFormat> _dataWithoutAI;
        private byte _minLength;
        private byte _maxLength;

        public ApplicationIdentifier(string ai, List<DataFormat> dataWithoutAI)
            : this(ai, (byte)ai.Length, dataWithoutAI)
        {
        }

        public ApplicationIdentifier(string ai, byte aiLength, List<DataFormat> dataWithoutAI)
        {
            this._ai = ai;
            this._aiLength = aiLength;
            this._dataWithoutAI = dataWithoutAI;

            this._minLength = aiLength;
            this._maxLength = aiLength;

            for (int i = 0; i < this._dataWithoutAI.Count; i++)
            {
                byte[] temp = this._dataWithoutAI[i].Length;
                this._minLength += temp[0];
                this._maxLength += temp[temp.Length - 1];
            }
            this._isFixedLength = this._minLength == this._maxLength;
        }
        /// <summary>
        /// 商品应用标识符
        /// </summary>
        public string AI
        {
            get { return this._ai; }
        }
        /// <summary>
        /// 标识符长度
        /// </summary>
        public byte AILength
        {
            get { return this._aiLength; }
        }
        /// <summary>
        /// 排除标识符后字符串的数据格式
        /// </summary>
        public List<DataFormat> DataWithoutAI
        {
            get { return this._dataWithoutAI; }
        }
        /// <summary>
        /// 是否定长
        /// </summary>
        public bool IsFixedLength
        {
            get { return this._isFixedLength; }
        }
        /// <summary>
        /// 获取该商品应用标识允许的最小长度(包含AI)
        /// </summary>
        /// <returns></returns>
        public byte MinLength
        {
            get { return this._minLength; }
        }
        /// <summary>
        /// 获取该商品应用标识允许的最大长度(包含AI)
        /// </summary>
        /// <returns></returns>
        public byte MaxLength
        {
            get { return this._maxLength; }
        }
    }
    /// <summary>
    /// 数据格式
    /// </summary>
    internal sealed class DataFormat
    {
        private AICharacter _character;
        private byte[] _length;
        /// <summary>
        /// 默认数据格式为数字
        /// </summary>
        /// <param name="length"></param>
        public DataFormat(byte[] length)
            : this(AICharacter.n, length)
        {
        }
        public DataFormat(AICharacter character, byte[] length)
        {
            this._character = character;
            this._length = length;
        }

        /// <summary>
        /// 数据类型
        /// </summary>
        public AICharacter Character
        { get { return this._character; } }
        /// <summary>
        /// 数据长度,数组长度为1时表示定长
        /// </summary>
        public byte[] Length
        { get { return this._length; } }
    }


GS1-128

/// <summary>
    /// GS1-128(UCC/EAN128)条形码,遵循标准GB/T 16986-2009
    /// </summary>
    public class GS1_128 : absCode128
    {
        private List<string> _aiList = new List<string>();//rawData分割后符合商品应用标识规范的字符串集合
        /// <summary>
        /// GS1-128(UCC/EAN128)条形码,非定长标识符后面必须跟空格,定长标识符带不带无所谓
        /// </summary>
        /// <param name="rawData">包含ASCII码表32~126,其中32对应的空格sp用来通知生成FNC1分割符</param>
        public GS1_128(string rawData)
            : base(rawData)
        {
        }
        /// <summary>
        /// 对应的ASCII码范围为32~126,其中32对应的空格sp用来通知生成FNC1分割符
        /// </summary>
        /// <returns></returns>
        protected override bool RawDataCheck()
        {
            this._presentationData = string.Empty;
            string[] tempArray = this._rawData.Split((char)32);//以空格为分隔符将字符串进行分割
            foreach (string ts in tempArray)
            {
                int ptr = 0;
                do
                {
                    string tempStr;
                    ApplicationIdentifier ai = AI.GetAI(ts.Substring(ptr));
                    int residuelength = ts.Length - ptr;//剩余字符串长度
                    if (ai == null || residuelength < ai.MinLength || (!ai.IsFixedLength && residuelength > ai.MaxLength))
                    {//第三个判定条件:因为不定长,而且经过空格分割,所以此时如果出现剩余字符串长度超出标识符最大长度规定,则认为错误
                        return false;
                    }
                    else
                    {
                        int length = Math.Min(ai.MaxLength, residuelength);
                        tempStr = ts.Substring(ptr, length);
                        ptr += length;
                    }
                    if (!AI.IsRight(ai, tempStr))
                    {
                        return false;
                    }
                    //展示数据加上括号
                    this._presentationData += string.Format("({0}){1}", tempStr.Substring(0, ai.AILength), tempStr.Substring(ai.AILength));

                    #region 修改为遵循预定义长度的AI后面才不加上FNC1,而不是实际定长的就不加上FNC1
                    //if (!ai.IsFixedLength)
                    //{
                    //    tempStr += (char)32;//为不定长AI加上空格,以便生成条形码时确认需要在此部分后面加入分隔符FNC1
                    //}
                    #endregion

                    this._aiList.Add(tempStr);
                }
                while (ptr < ts.Length);
            }

            //是否要将_aiList进行排序,将预定长的放在前面以符合 先定长后变长 原则
            //如果修改,则需将展示数据部分重新处理

            return true;
        }

        protected override string GetEncodedData()
        {
            StringBuilder tempBuilder = new StringBuilder();
            CharacterSet nowCharacterSet;
            //校验字符
            int checkNum = Code128.GetStartIndex(this._aiList[0], out nowCharacterSet);
            tempBuilder.Append(Code128.BSList[checkNum]);//加上起始符
            tempBuilder.Append(Code128.BSList[Code128.FNC1]);//加上第一个FNC1表示当前是GS1-128
            checkNum += Code128.FNC1;
            int nowWeight = 2;//当前权值

            for (int i = 0; i < this._aiList.Count; i++)
            {
                string tempStr = this._aiList[i];
                int nowIndex = 0;
                #region 修改为遵循预定义长度的AI后面才不加上FNC1,而不是实际定长的就不加上FNC1
                //bool isEndWithSP = tempStr[tempStr.Length - 1] == (char)32;
                //if (isEndWithSP)
                //{
                //    tempStr = tempStr.Substring(0, tempStr.Length - 1);
                //}
                #endregion
                Code128.GetEncodedData(tempStr, tempBuilder, ref nowCharacterSet, ref nowIndex, ref nowWeight, ref checkNum);
                #region 修改为遵循预定义长度的AI后面才不加上FNC1,而不是实际定长的就不加上FNC1
                //if (isEndWithSP && i != this._aiList.Count - 1)
                //{
                //    //非定长标识符后面加上FNC1,此时FNC1作为分隔符存在
                //    Code128.EncodingCommon(tempBuilder, Code128.FNC1, ref nowWeight, ref checkNum);
                //}
                #endregion
                if (!AI.IsPredefinedAI(tempStr) && i != this._aiList.Count - 1)
                {
                    //非预定长标识符后面加上FNC1,此时FNC1作为分隔符存在
                    Code128.EncodingCommon(tempBuilder, Code128.FNC1, ref nowWeight, ref checkNum);
                }
            }

            checkNum %= 103;
            tempBuilder.Append(Code128.BSList[checkNum]);//加上校验符
            tempBuilder.Append(Code128.BSList[Code128.Stop]);//加上结束符
            return tempBuilder.ToString();
        }
    }


 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值