3

这是我的功能的要求:

取以下字符串:

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”。这就是棘手的地方。现在我需要十六进制“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}
  • 在旁注中,我意识到我需要处理偶数/奇数字段长度来处理我正在编写的实际函数,但让我担心 =]
4

5 回答 5

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

您应该能够将其调整为具有必要警告的更广泛的解决方案。我对它进行了粗略的测试,它似乎可以在我扔给它的简单字节数组上工作。希望这可以帮助!

于 2012-07-13T19:01:05.720 回答
0

不确定这是否是家庭作业,但左移和组合部分看起来像这样:

var pos = 0;
var newByte = b1[pos] << 4;
newByte |= b2[pos]

显然你会想在一个循环中做到这一点,并考虑到 2 个数组的长度

于 2012-07-13T18:15:11.307 回答
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

...符合规定的期望结果。

于 2012-07-13T18:20:46.097 回答
0

我会做一个 BCD 类。然后 BCD.ToByteArray() 会以 Byte[] 格式为您提供 BCD 的当前表示,而 BCD.ToString() 将提供字符串格式。在内部将 BCD 存储为每个 BCD 位一个数组元素。如果你设计自己的数据结构而不是试图让 Byte[] 做它不打算做的事情,你会做得更好。

于 2012-07-13T18:32:23.223 回答
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
于 2012-07-13T19:00:32.843 回答