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」です。ここがややこしいところです。ここで、2 つのフィールド間の区切り記号 (=) を表す 16 進数の 'D' が必要です。バイト配列の 12 インデックスの上位ニブルに 16 進数が表示されます。バイト配列の残りは、bcd 形式でエンコードされた 2 番目のフィールド「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

あなたが本当に必要としているのは、メモリの 2 番目のブロック全体を 4 ビット左にシフトすることです。つまり、コピーするだけでなく、バ​​イト 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 の値にするためにどのように計算したかはわかりません。:)

述べられた望ましい結果に基づいて、セパレータニブルを2番目の配列の最初のバイトにシフトするだけです。

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

わかった:

    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 に答える
0

BCDクラスを作ります。次に、BCD.ToByteArray() は BCD の現在の表現を Byte[] 形式で提供し、BCD.ToString() は文字列形式を提供します。BCD 桁ごとに 1 つの配列要素として BCD を内部的に格納します。意図しないことを Byte[] に行わせるのではなく、独自のデータ構造を設計した方がよいでしょう。

于 2012-07-13T18:32:23.223 に答える