我有一个由CashRegister Machine创建的Hex文件。我必须在。
中阅读此文件文件使用下面详述的格式。它就像套接字包。
代码数据:2字节
PLU代码数据:7字节
单价数据:5字节
数量数据:5字节
总金额数据:5字节
PLU名称数据:18字节
税率数据:1字节
长度:24 + 19字节
我用二进制阅读器读取hex文件,然后插入单位价格字节数组。
byte[] bytes = { data[21], data[22], data[23], data[24], data[25] }; // BCD Byte Array
此数组为单价。但是,如何将此数字转换为十进制数。并且信息说数量:BCD最后一个数字应该是十进制 - 这是什么意思?感谢。
答案 0 :(得分:8)
BCD编号将0-9的值编码为4位。在打包的BCD(可能是你正在处理的)中,一个字节用于包含两个值0-9,每个字节的半字节(4位)中有一个。要转换为int,你必须做一点点摆弄。例如,以下内容将BCD字节数组转换为int,最多可容纳9位数字。如果您的输入数量超过9 bcd,请使用long。
// assume byte[] bcds is input
int result = 0;
foreach(byte bcd in bcds) {
result *= 100;
result += (10 * (bcd >> 4));
result += bcd & 0xf;
}
这假设每个字节都存储为big-endian BCD,其中最高有效位在字节的最高有效半字节中。这是Wikipedia page for BCD中描述的更常见的实现。如果您正在处理little-endian BCD,那么for循环中的转换代码将是
result *= 100;
result += (10 * (bcd & 0xf));
result += bcd >> 4;
您还需要确保数组具有正确的字节顺序,即数组中的第一个字节是否包含最重要的两位数,或最不重要的两位数。例如,使用压缩BCD,数字123456将适合3个字节。字节[0]或字节[2]中是12吗?如果您的字节顺序与我的假设不同,您需要调整上面的循环以反转顺序。我假设12是在byte [0](大端,最左边的字节中最高位)。
至于描述为BCD和十进制的数量,我需要查看实际值以了解他们所谈论的内容。
答案 1 :(得分:4)
每个字节是两个十进制数字,每个半字节一个。如果将字节显示为十六进制,则可以轻松读取数字。
0x08 0x27 0x42 0x17 0x75 = 827,421,775
你可以像这样得到高低音:
int high = currentByte >> 4;
int low = currentByte & 0xF;
将每个字节转换为如下数字:
int number = 10 * high + low;
但请记住,每个字节比下一个字节大100倍。
如果数量为3位小数,则只需将最终数字除以1,000即可获得实际值。
答案 2 :(得分:4)
CORRECT代码:
// assume byte[] bcds is input
int result = 0;
foreach(byte bcd in bcds) {
result *= 100;
result += (10 * (bcd >> 4));
result += bcd & 0xf;
}
您还可以通过创建公共静态类来创建byte []的自定义扩展:
public static class BitConverterExtension
{
public static UInt64 FromBCDToExtUInt64(this byte[] b, byte[] bcds, uint nBytes, uint startOf)
{
UInt64 result = 0;
uint i = 0;
for (i = 0; i < nBytes; i++)
{
result *= 100;
result += (UInt64)(10 * (bcds[startOf + i] >> 4));
result += (UInt64)(bcds[startOf + i] & 0xf);
}
return (result);
}
}
答案 3 :(得分:0)
对于这个问题,我的回答可能有点迟,但这是我如何解决这个问题:
1-首先,我需要找到数字的长度,例如:3422 - &gt; 4,100 - &gt; 3
public static class NumbersUtility
{
public static int FindNumberLength(int number)
{
return Convert.ToInt32( Math.Floor(Math.Log(number,10))+1);
}
public static int FindNumberDivisor(int number)
{
return Convert.ToInt32(Math.Pow(10, FindNumberLength(number)-1));
}
public static int[] FindNumberElements(int number)
{
int[] elements = new int[FindNumberLength(number)];
int divisor = FindNumberDivisor(number);
for (int i = 0; i < elements.Length; i++)
{
elements[i] = number/divisor;
number %= divisor;
divisor /= 10;
}
return elements;
}
}
之后我将数字拆分成一个数组,这样可以更容易地遍历和处理数字。但有一点需要注意,如果数字是奇数长度,则必须将零添加到数组的开头。
public static byte[] IntToBCD(int[] input, bool isLittleEndian = false)
{
byte[] outArr = new byte[Convert.ToInt32(Math.Ceiling((double) input.Length/2))];
//Handle the case of an odd number in which a zero should be added at the beginning
if (input.Length%2 != 0)
{
//Use a temp array to expand the old one, you can use lists or
//anyother datastructure if you wish to
int[] newInput = new int[input.Length+1];
Array.Copy(input,0,newInput,1,input.Length);
newInput[0] = 0;
input = newInput;
//Dispose the temp array
newInput = null;
}
for (int i = 0; i < outArr.Length; i++)
{
outArr[i]=(byte)(input[i*2]<<4);
outArr[i]|=(byte)(input[i*2+1]);
}
return outArr;
}
答案 4 :(得分:0)
我编写了这段代码并为我工作:
{
l: true,
H: true,
R: true,
s: true,
ip: '127.0.0.1',
port: '8080',
env: 'dev'
}
这是反向代码:
public uint BCD5ToInt(byte [] bcd)
{
uint outInt=0;
for (int i = 0; i < bcd.Length; i++)
{
int mul = (int)Math.Pow(10,(i*2));
outInt += (uint) (((bcd[i] & 0xF)) * mul);
mul = (int)Math.Pow(10, (i * 2) + 1);
outInt +=(uint)( ((bcd[i] >> 4) ) * mul);
}
return outInt;
}
这是测试代码:
// Convert an unsigned integer into 5 bytes of
public byte[] IntToBCD5(uint numericvalue, int bytesize = 5)
{
byte[] bcd = new byte[bytesize];
for (int byteNo = 0; byteNo < bytesize; ++byteNo)
bcd[byteNo] = 0;
for (int digit = 0; digit < bytesize * 2; ++digit)
{
uint hexpart = numericvalue % 10;
bcd[digit / 2] |= (byte)(hexpart << ((digit % 2) * 4));
numericvalue /= 10;
}
return bcd;
}