根据我对 Code128 条形码(与大多数其他标准条形码类型截然不同)的校验位计算的理解*,我下面的代码是正确的。然而,我希望那些可能更了解/有一些经验观察/来自战壕(或实验室)外套上的泥土的人进行“健全性检查”。
条形码中的每个字符(从左侧)首先被转换为其 ASCII 代码(IOW,条形码字符“1”将被视为其 ASCII 代码 49 等),然后将该值乘以其在字符数组中的序号位置。
例如对于制作的条形码编号“123456789”,“1”等于 49,“2”等于 50,...“9”等于 57。
然后,将每个字符的序数位置乘以其 ASCII 值。例如,1*49 == 49、2*50==100、... 9*57==513。 然后将所有这些相加,得出(在本例中)2,445。
下一步是将该数字除以 Code128“幻数”103;您感兴趣的值是模数。所以,在这种情况下,2445 % 103 == 76。
倒数第二个 - 最后,转换该值 (76),将其视为 ASCII 代码,将另一个方向返回到其“表示”值,即“L”。
最后,将计算出的字符附加到原始条形码中。确实如此(尽管有更多的麻烦或再见),您最终得到的值为“123456789L”
如果这不是正确的值,那么我的理解有误。
这里有一些条形码:
0) 123456789
1) 12345678
2) 1234567
3) 123456
...以及它们应该如何与计算出的校验位一起出现(并且使用下面的代码):
0) 123456789L
1) 12345678N
2) 1234567*
3) 123456E
最后但并非最不重要的一点是,这是我用来计算 Code128 校验位的代码:
private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
const int CODE_128_DIVISOR = 103;
string barCode = textBoxRawCode128.Text.Trim();
int runningTotal = 0;
for (int i = barCode.Length - 1; i > -1; i--)
{
char valToConvertToASCII = Convert.ToChar(barCode[i]);
int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
runningTotal += (valToMultiply*(i + 1));
}
int code128Modulus = runningTotal%CODE_128_DIVISOR;
textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
return valToConvertToASCII;
}
我不太理解布莱恩·安德森的回答;他可能是对的(可能是),但我认为就校验位计算而言,起始位和停止位将被忽略。它们的存在不就是为了让条形码扫描仪知道从哪一点开始注意,然后从哪一点开始可以恢复电子暂停吗?
然后数学计算(假设 Brian 关于需要从 ASCII 值中减去 32 的说法是正确的)将是:
(17*1)+(18*2)+(19*3)+(20*4)+(21*5)+(22*6)+(23*7)+(24*8)+(25*9)
-or:
17 + 36 + 57 + 80 + 105 + 132 + 161 + 192 + 225 == 1005
为什么计算中会包含起始字符,而不包含终止字符?
由于 1005 % 103 == 78,校验位将是...“N”...还是 (78-32 == 46)“-”?
如果同时包含停止字符和开始字符,那么当然也会改变解决方案......
我承认我不太喜欢条形码,所以我可能见过这样的东西,只是没有注意到/注意,但是可以条形码有“-”和“”这样的校验位吗?这看起来很奇怪;我希望它们即使不仅仅是数字,也始终是字母数字。如果我的怀疑是正确的,当计算最终以“-”或“”或“~”等松散的校验数字结束时,该怎么办?
因此,如果我理解 Brian 和我正确阅读的其他来源,我将从条形码扫描仪中读取语义解码的内容:
[startChar]123456789[checkDigit][stopChar]
...但是这会在逻辑上删除停止字符——因为它不是校验位计算的一部分——而且(逻辑上不完全如此)也会删除校验位,所以我实际得到的是:
[startChar]123456789
...并对其进行处理并计算校验位以显示条形码的人类可读表示:
123456789[checkDigit]
并且由于如果扫描了条形码,则显然可以看到起始字符(?),因此我可以将其预先添加到要计算的 runningTotal 值中;因此,我的代码现在是:
private void buttonAppendCode128CheckDigit_Click(object sender, EventArgs e)
{
const int CODE_128_DIVISOR = 103;
string barCode = textBoxRawCode128.Text.Trim();
int runningTotal = ConvertToASCIIInt(barcode[0]); // Start with the value of the start char; this should always be either 103 (Code128A), 104 (Code128B), or 105 (Code128C); 106 is the stop char
for (int i = barCode.Length - 1; i > 0; i--) // now disregarding already calculated first element by ignoring element 0
{
char valToConvertToASCII = Convert.ToChar(barCode[i]);
int valToMultiply = ConvertToASCIIInt(valToConvertToASCII);
runningTotal += (valToMultiply*(i + 1));
}
int code128Modulus = runningTotal%CODE_128_DIVISOR;
textBoxCode128WithCheckDigit.Text = barCode + ConvertToASCIIChar(code128Modulus);
}
private char ConvertToASCIIChar(int code128Modulus)
{
return (char) code128Modulus;
}
private int ConvertToASCIIInt(char valToConvertToASCII)
{
const int ASCII_ADJUSTMENT_VAL = 32;
return valToConvertToASCII-ASCII_ADJUSTMENT_VAL;
}
您可能缺少代码 128A (103)、128B (104) 或 128C (105) 的起始字符。该数字用“*1”加权,就像条形码字符串中的第一个字符一样。我还认为您必须使用 Code 128 值(即 ASCII_value_of_character - 32)进行数学计算。因此,对于字符串“123456789”,我得到“104, 17, 18, 19, 20, 21, 22, 23, 24, 25, 79, 106”,包括开始 128B (104)、停止 (106) 和校验和 79 (1109 % 103)。
这里有一个稍微不同的方法,以防对其他人有帮助。变化是:
注意:校验和计算中不使用停止代码。
var checkSum = CalcCheckSum("TEST1234", 103);
public int CalcCheckSum(string barcodeValue, int startCode = 104)
{
int checkSum = 0;
try
{
//Add the startCode to the total. You could just add
//the startCode value without checking for zero.
var checkSumTotal = startCode == 0 ? 104 : startCode;
//Split the string into an array of characters.
char[] barcodeChars = barcodeValue.ToCharArray();
int x = 1;
//Loop through the array to get the ASCII value
//by using type int and then subtract 32 to get
//the Code 128 value. The resulting value gets
//multiplied by its position x.
foreach (var digit in barcodeChars)
{
checkSumTotal += ((int)digit - 32) * x;
x++;
}
//Take the total and find the remainder when
//you multiply by 103
checkSum = checkSumTotal % 103;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return checkSum;
}
这是有关 Code 128 的 wiki 链接。