以下是我的功能要求:
取以下字符串:
6900460420006149231=13050010300100000
并将其转换为以下字节数组:
{ 0x37, 0x06, 0x90, 0x04, 0x60, 0x42, 0x00, 0x06, 0x14, 0x92, 0x31, 0xD1, 0x30, 0x50, 0x01, 0x03, 0x00, 0x10, 0x00, 0x00 }
第一个字节0x37是二进制字符串的原始长度。接下来的10个字节是以bcd格式编码的字符串“6900460420006149231”。这是变得棘手的地方。现在我需要Hex'D'来表示两个字段之间的分隔符(=)。您可以在字节数组中看到12索引的高半字节中的十六进制。字节数组的其余部分是以bcd格式编码的第二个字段“13050010300100000”。如果原始长度是奇数,我将前导零填充到未使用数据的前半个字节。
我不希望任何人完全实施,所以让我们分解并解决我遇到麻烦的地方。 让我们说:
byte[] field1Bytes = { 0x06, 0x90, 0x04, 0x60, 0x42, 0x00, 0x06, 0x14, 0x92, 0x31 }
byte[] field2Bytes = { 0x01, 0x30, 0x50, 0x01, 0x03, 0x00, 0x10, 0x00, 0x00 }
byte separator = 13; // D 0x0D
如果我只使用Array.Copy,我最终会得到:
{ 0x06, 0x90, 0x04, 0x60, 0x42, 0x00, 0x06, 0x14, 0x92, 0x31, 0x0D, 0x01, 0x30, 0x50, 0x01, 0x03, 0x00, 0x10, 0x00, 0x00 }
上面的字节数组并不是我所需要的..任何关于如何实现以下函数的想法让我更接近我想要实现的目标:
byte[] ShiftLeftAndCombine(byte[] b1, byte[] b2)
,其中
ShiftLeftAndCombine({0x0d}, {0x01, 0x30})
将返回
{0xd1, 0x30}
答案 0 :(得分:1)
你真正需要做的是将整个第二块内存移到四位,在我看来。这意味着你将做的不仅仅是复制,你将把字节n + 1的“前导”(最高有效)位移到“尾随”(最低有效)第n个字节。这是一个字节数组的通用“位移位器”。
byte[] shiftBlock(byte[] bytes, short bitShift)
{
byte[] newBytes = new byte[bytes.Length+1];
for (int index=0;index < bytes.Length; index++)
{
// Each new byte is the current byte shifted left by "bitShift" bits,
// followed by the first 8-bitShift bits of the next byte OR zero,
// if we're at the end of the array. Shift the next-bytes bits to
// the right, and OR the result together.
byte newByteMSB = (byte)(bytes[index] << bitShift); // shift left bitShift bits
byte newByteLSB = (byte)((index==bytes.Length-1)?((byte)0):(bytes[index+1]));
newByteLSB = (byte) (newByteLSB >> (8-bitShift));
newBytes[index] = (byte) ( newByteMSB | newByteLSB);
}
return newBytes;
}
您应该能够根据必要的警告将其调整为更广泛的解决方案。我给它一个粗略的测试,它似乎适用于我抛出的简单字节数组。希望这有帮助!
答案 1 :(得分:0)
不确定这是否是作业,但左移和合并部分看起来像这样:
var pos = 0;
var newByte = b1[pos] << 4;
newByte |= b2[pos]
显然你会想要在一个循环中这样做,并考虑到2个数组的长度
答案 2 :(得分:0)
编辑修改为不在结果中包含原始长度。
希望这会有所帮助。但是,不知道如何计算原始长度的值为0x37。 :)
根据所述的预期结果,您只需将分隔符nybble转换为第二个数组的第一个字节。
byte[] field1Bytes = { 0x06, 0x90, 0x04, 0x60, 0x42, 0x00, 0x06, 0x14, 0x92, 0x31 } ;
byte[] field2Bytes = { 0x01, 0x30, 0x50, 0x01, 0x03, 0x00, 0x10, 0x00, 0x00 } ;
byte separator = 13; // D 0x0D
byte[] result = new byte[field1Bytes.Length + field2Bytes.Length];
Array.Copy(field1Bytes, 0, result, 0, field1Bytes.Length);
Array.Copy(field2Bytes, 0, result, field1Bytes.Length, field2Bytes.Length);
// shift the separator into the first byte of the second array in the result
result[field1Bytes.Length] |= (byte)(separator << 4);
这会产生:
0x06 0x90 0x04 0x60 0x42 0x00 0x06 0x14 0x92 0x31 0xd1 0x30 0x50 0x01 0x03 0x00 0x10 0x00 0x00
...符合规定的预期结果。
答案 3 :(得分:0)
我会做一个BCD课。然后BCD.ToByteArray()将以Byte []格式给出BCD的当前表示,BCD.ToString()将给出字符串格式。内部存储BCD作为每个BCD数字的一个数组元素。如果你设计自己的数据结构而不是试图让Byte []做你不打算做的事情,你会更好。
答案 4 :(得分:0)
好的,我明白了:
static void Main(string[] args)
{
const string rawTrack = "6900460420006149231=13050010300100000";
var byteList = new LinkedList<byte>();
foreach (var c in rawTrack)
{
if(c.Equals('='))
{
byteList.AddLast(13);
continue;
}
var bytes = Formatters.Bcd.GetBytes(new string(c, 1)); // for 9 gives 0x09
byteList.AddLast(bytes[0]);
}
// Adjust Buffer if odd length
if(rawTrack.Length % 2 != 0)
{
byteList.AddFirst(0);
}
var result = new byte[byteList.Count / 2];
var buffer = new byte[byteList.Count];
byteList.CopyTo(buffer, 0);
var j = 0;
for(var i = 0; i < buffer.Length - 1; i += 2, j++ )
{
result[j] = CombineLowNibble(buffer[i], buffer[i + 1]);
}
Console.WriteLine(BitConverter.ToString(result));
}
private static byte CombineLowNibble(byte b, byte b1)
{
return (byte) ((b << 4) | b1);
}
结果如下:
06-90-04-60-42-00-06-14-92-31-D1-30-50-01-03-00-10-00-00