2012-07-28 372 views
3

我有一个由CashRegister Machine创建的十六进制文件。我必须读取此文件。C#字节[]到BCD和BCD到INT

文件使用以下详细格式。它就像套接字包一样。

代码数据:2字节
PLU代码数据:7字节
单价数据:5字节
数量数据:5字节
总金额数据:5字节
PLU名称数据:18字节
税率数据:1个字节
长度:24 + 19字节

  • PLU码格式是BCD
  • 单价1-9999999999(BCD)
  • 量1-9999999999(BCD最后3个数字应该是十进制)
  • 总量1-9999999999(BCD)

我在十六进制文件用阅读二进制阅读器,然后插入单位价格字节数组。

byte[] bytes = { data[21], data[22], data[23], data[24], data[25] }; // BCD Byte Array 

此数组为单价。但是,我怎样才能将这个数字转换为十进制数。信息说,对于数量:BCD最后的数字应该是小数 - 这是什么意思?谢谢。

+1

非常不清楚的问题,请澄清/详细说明。 – Spikeh 2012-07-28 12:34:11

+0

显示“byte [] bytes”内容的示例以及您期望的输出。看看''BinaryReader.ReadDecimal()'](http://msdn.microsoft.com/en-us/library/system.io.binaryreader.readdecimal.aspx)。 – CodeCaster 2012-07-28 12:36:31

+1

我试图阐述它。字节有一个数字,但我怎么能读为int。 – xFireTR 2012-07-28 12:45:26

回答

7

BCD编号将0-9的值编码为4位。在打包的BCD中(可能是你正在处理的内容),一个字节被用来包含0-9的两个值,每个半字节(4位)包含一个字节。要转换为一个int,你必须做一些小动作。例如,下面的代码将把一个BCD字节数组转换为一个int,它可以保存9位数字。如果您输入的数字超过9位,请使用长时间。

// assume byte[] bcds is input 
int result = 0; 
foreach(byte bcd in bcds) { 
    result *= 100; 
    result += (10 * (bcd >> 4)); 
    result += bcd & 0xf; 
} 

这假定每个字节存储为大端BCD,其中最显著数字是在字节的最显著四位。这是Wikipedia page for BCD中描述的更常见的实现。如果你正在处理little-endian的BCD,在for循环转换代码将

result *= 100; 
    result += (10 * (bcd & 0xf)); 
    result += bcd >> 4; 

你还需要确保你的阵列,即一个正确的顺序,做数组中的第一个字节包含最重要的两位数字或最不重要的两位数字。例如,数字123456将使用打包的BCD放入3个字节。在字节[0]或字节[2]中是12?如果您的字节顺序与我的假设不同,您需要调整上面的循环以颠倒顺序。我假设12在字节[0](大端,在最左边的字节中最有效的数字)。

至于描述为BCD和小数的数量,我需要看实际值来理解他们在说什么。

+0

bcd >> = 4;不起作用。您需要复制该字节以修改它。 – 2013-11-18 15:45:59

+0

@SamLeach - 谢谢你的提升。我把它写在了我的头顶。我已经根据你的建议修复了它,并修复了我在此过程中注意到的另一个错误。上面的代码现在已经过测试和工作。 – hatchet 2013-11-18 17:44:33

4

每个字节是两位十进制数字,每个半字节一个。如果将字节显示为十六进制,则可以轻松读取该数字。

0x08 0x27 0x42 0x17 0x75 = 827,421,775 

就可以得到高和低半字节是这样的:

int high = currentByte >> 4; 
int low = currentByte & 0xF; 

每个字节转换成数是这样的:

int number = 10 * high + low; 

但请记住,每个字节是那么大了100倍下一个字节。

数量有3位小数,只需将最终数字除以1000即可得到实际值。

2

正确的代码:为

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); 

    } 
} 
0

我的回答可能是有点晚:

// assume byte[] bcds is input 
int result = 0; 
foreach(byte bcd in bcds) { 
    result *= 100; 
    result += (10 * (bcd >> 4)); 
    result += bcd & 0xf; 
} 

您也可以通过创建一个公共静态类来创建一个自定义扩展到一个byte []问题,但这里是我如何解决这个问题:

1-首先我需要找到数字的长度例如:3422 - > 4,100 - > 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; 
    }