如何验证UPC或EAN代码?

Zac*_*son 20 .net c# checksum barcode

我需要一个C#.NET函数来评估键入或扫描的条形码是否是有效的全球贸易项目编号(UPC或EAN).

条形码校验位

条形码编号的最后一位是计算机检查数字,用于确保条形码的正确编码.GTIN校验数字计算器

Zac*_*son 22

public static bool IsValidGtin(string code)
{
    if (code != (new Regex("[^0-9]")).Replace(code, ""))
    {
        // is not numeric
        return false;
    }
    // pad with zeros to lengthen to 14 digits
    switch (code.Length)
    {
        case 8:
            code = "000000" + code;
            break;
        case 12:
            code = "00" + code;
            break;
        case 13:
            code = "0" + code;
            break;
        case 14:
            break;
        default:
            // wrong number of digits
            return false;
    }
    // calculate check digit
    int[] a = new int[13];
    a[0] = int.Parse(code[0].ToString()) * 3;
    a[1] = int.Parse(code[1].ToString());
    a[2] = int.Parse(code[2].ToString()) * 3;
    a[3] = int.Parse(code[3].ToString());
    a[4] = int.Parse(code[4].ToString()) * 3;
    a[5] = int.Parse(code[5].ToString());
    a[6] = int.Parse(code[6].ToString()) * 3;
    a[7] = int.Parse(code[7].ToString());
    a[8] = int.Parse(code[8].ToString()) * 3;
    a[9] = int.Parse(code[9].ToString());
    a[10] = int.Parse(code[10].ToString()) * 3;
    a[11] = int.Parse(code[11].ToString());
    a[12] = int.Parse(code[12].ToString()) * 3;
    int sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + a[11] + a[12];
    int check = (10 - (sum % 10)) % 10;
    // evaluate check digit
    int last = int.Parse(code[13].ToString());
    return check == last;
}
Run Code Online (Sandbox Code Playgroud)

  • 有点麻烦的方法.在我看来,使用单个循环会更好 (3认同)

Luc*_*lho 17

GS1 US在PDF文档中发布了GTIN的校验位计算算法(删除了不断变化的链接).

以下代码使用linq检查GTIN条形码的最后一位数:GTIN-8,GTIN-12(UPC),GTIN-13(EAN)和GTIN-14(ITF-14).

private static Regex _gtinRegex = new System.Text.RegularExpressions.Regex("^(\\d{8}|\\d{12,14})$");
public static bool IsValidGtin(string code)
{
    if (!(_gtinRegex.IsMatch(code))) return false; // check if all digits and with 8, 12, 13 or 14 digits
    code = code.PadLeft(14, '0'); // stuff zeros at start to garantee 14 digits
    int[] mult = Enumerable.Range(0, 13).Select(i => ((int)(code[i] - '0')) * ((i % 2 == 0) ? 3 : 1)).ToArray(); // STEP 1: without check digit, "Multiply value of each position" by 3 or 1
    int sum = mult.Sum(); // STEP 2: "Add results together to create sum"
    return (10 - (sum % 10)) % 10 == int.Parse(code[13].ToString()); // STEP 3 Equivalent to "Subtract the sum from the nearest equal or higher multiple of ten = CHECK DIGIT"
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*Dev 13

上面的解决方案计算校验位并将其与给定数字进行比较,忽略了它被设计为以更简单的方式验证的事实.

  1. 将所有数字(包括校验位)乘以3或1和求和.
  2. 检查总和是否是10的倍数

根据卢西亚诺的回答:

private static Regex _gtinRegex = new Regex("^(\\d{8}|\\d{12,14})$");
public static bool IsValidGtin(string code)
{
    if (!(_gtinRegex.IsMatch(code))) return false;
    code = code.PadLeft(14, '0');
    int sum = code.Select((c,i) => (c - '0')  * ((i % 2 == 0) ? 3 : 1)).Sum();
    return (sum % 10) == 0;
}
Run Code Online (Sandbox Code Playgroud)


nul*_*oop 5

可变长度的EAN

    public static bool IsValidEan13(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 13);
    }

    public static bool IsValidEan12(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 12);
    }

    public static bool IsValidEan14(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 14);
    }

    public static bool IsValidEan8(string eanBarcode)
    {
        return IsValidEan(eanBarcode, 8);
    }

    private static bool IsValidEan(string eanBarcode, int length)
    {
        if (eanBarcode.Length != length) return false;
        var allDigits = eanBarcode.Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();
        var s = length%2 == 0 ? 3 : 1;
        var s2 = s == 3 ? 1 : 3;
        return allDigits.Last() == (10 - (allDigits.Take(length-1).Select((c, ci) => c*(ci%2 == 0 ? s : s2)).Sum()%10))%10;
    }

    [Test]
    [TestCaseSource("Ean_13_TestCases")]
    public void Check_Ean13_Is_Valid(string ean, bool isValid)
    {
        BlinkBuilder.IsValidEan13(ean).Should().Be(isValid);
    }

    private static IEnumerable<object[]> Ean_13_TestCases()
    {
        yield return new object[] { "9781118143308", true };
        yield return new object[] { "978111814330", false };
        yield return new object[] { "97811181433081", false };
        yield return new object[] { "5017188883399", true };
    }

    [Test]
    [TestCaseSource("Ean_8_TestCases")]
    public void Check_Ean8_Is_Valid(string ean, bool isValid)
    {
        BlinkBuilder.IsValidEan8(ean).Should().Be(isValid);
    }

    private static IEnumerable<object[]> Ean_8_TestCases()
    {
        yield return new object[] { "12345670", true };
        yield return new object[] { "12345679", false };
        yield return new object[] { "55432214", true  };
        yield return new object[] { "55432213", false };
        yield return new object[] { "55432215", false };
    }
Run Code Online (Sandbox Code Playgroud)

编辑

我正在构建此代码的项目现已启动并运行 - 它是全面的条形码数据库和工具集的一部分 - 并且包括批量条形码验证器(非注册用户批量100个,注册10,000个) - https:// blinked.in/tools/validator