0

予測:

byte []をリトルエンディアンからビッグエンディアンに変換することは、byte[]の各バイトのビットの順序を逆にすることを意味します。

これが正しいと仮定して、私はこれを理解するために次のことを試みました:

byte[] data = new byte[] { 1, 2, 3, 4, 5, 15, 24 };
byte[] inverted = ToBig(data);

var little = new BitArray(data);
var big = new BitArray(inverted);

int i = 1;

foreach (bool b in little)
{
    Console.Write(b ? "1" : "0");
    if (i == 8)
    {
        i = 0;
        Console.Write(" ");
    }
    i++;
}

Console.WriteLine();

i = 1;

foreach (bool b in big)
{
    Console.Write(b ? "1" : "0");
    if (i == 8)
    {
        i = 0;
        Console.Write(" ");
    }
    i++;
}

Console.WriteLine();

Console.WriteLine(BitConverter.ToString(data));
Console.WriteLine(BitConverter.ToString(ToBig(data)));

foreach (byte b in data)
{
    Console.Write("{0} ", b);
}

Console.WriteLine();

foreach (byte b in inverted)
{
    Console.Write("{0} ", b);
}

変換方法:

private static byte[] ToBig(byte[] data)
{
    byte[] inverted = new byte[data.Length];

    for (int i = 0; i < data.Length; i++)
    {
        var bits = new BitArray(new byte[] { data[i] });
        var invertedBits = new BitArray(bits.Count);

        int x = 0;

        for (int p = bits.Count - 1; p >= 0; p--)
        {
            invertedBits[x] = bits[p];
            x++;
        }

        invertedBits.CopyTo(inverted, i);
    }

    return inverted;
}

この小さなアプリケーションの出力は、私が期待したものとは異なります。

00000001 00000010 00000011 00000100 00000101 00001111 00011000

00000001 00000010 00000011 00000100 00000101 00001111 00011000 

80-40-C0-20-A0-F0-18

01-02-03-04-05-0F-18

1 2 3 4 5 15 24 

1 2 3 4 5 15 24 

何らかの理由で、BitConverterを使用して印刷しない限り、データは同じままです。

何がわからないの?

アップデート

新しいコードは次の出力を生成します。

10000000 01000000 11000000 00100000 10100000 11110000 00011000 

00000001 00000010 00000011 00000100 00000101 00001111 00011000 

01-02-03-04-05-0F-18

80-40-C0-20-A0-F0-18

1 2 3 4 5 15 24 

128 64 192 32 160 240 24 

しかし、今言われているように、ビットではなくバイトを反転する必要があるため、とにかく私の方法は正しくありませんか?

私が一緒に働いているこのハードウェア開発者は、データを読み取ることができないため、ビットを反転するように指示しました。

私がこれを使用しているコンテキスト

これを使用するアプリケーションは、実際には数値では機能しません。

私はビットのストリームをファイルに保存することになっています

1 =白、0=黒。

それらは、ビットマップ256x64のピクセルを表します。

バイト0からバイト31は、ピクセルの最初の行を表します。バイト32からバイト63は、ピクセルの2番目の行を表します。

私はこれらのビットを出力するコードを持っています...しかし開発者はそれらが間違った順序であると私に言っています...彼はバイトは問題ないがビットはそうではないと言います。

だから私は混乱したままです:p

4

4 に答える 4

6

いいえ。エンディアンとは、ビットではなくバイトの順序を指します。ビッグエンディアンシステムは最上位バイトを最初に格納し、リトルエンディアンシステムは最下位バイトを最初に格納します。バイト内のビットは同じ順序のままです。

ToBig()関数は、ビットスワップされたデータではなく、元のデータを返しているようです。

于 2009-03-09T19:52:08.817 に答える
2

この時点で、あなたの方法は正しいかもしれません。エンディアンにはさまざまな意味があり、ハードウェアによって異なります。

通常、コンピューティング プラットフォーム間の変換に使用されます。ほとんどの CPU ベンダー (現在) は、異なるチップセットに対して同じビット順序を使用していますが、異なるバイト順序を使用しています。つまり、あるシステムから別のシステムに 2 バイトの int を渡す場合、ビットはそのままにして、バイト 1 と 2 を交換します。つまり、次のようになります。

int somenumber -> byte[2]: somenumber[high],somenumber[low] ->  
byte[2]: somenumber[low],somenumber[high] -> int newNumber

ただし、これは常に正しいとは限りません。一部のハードウェアはまだ反転 BIT 順序を使用しているため、あなたが持っているものは正しいかもしれません。ハードウェア開発者を信頼する必要があります。またはさらに調べます。

ウィキペディアでこれを読むことをお勧めします-常に優れた情報源です。

http://en.wikipedia.org/wiki/エンディアンネス


ToBig メソッドにバグがあります。

最後に:

 invertedBits.CopyTo(data, i);
}

return data;

それを次のように変更する必要があります。

byte[] newData = new byte[data.Length];
invertedBits.CopyTo(newData, i);
}
return newData;

入力データをリセットしているため、両方の配列が反転されています。問題は、配列が参照型であるため、元のデータを変更できることです。

于 2009-03-09T19:54:40.887 に答える
2

grayfade が既に述べたように、エンディアンはビット順序に関するものではありません。

コードが期待どおりに動作しない理由は、送信する配列が ToBig メソッドによって変更されるためです。つまり、メソッドを呼び出した後、配列は反転され、同じ配列を指す 2 つの参照だけにdataなります。inverted

メソッドの修正版を次に示します。

private static byte[] ToBig(byte[] data) {
   byte[] result = new byte[data.length];
   for (int i = 0; i < data.Length; i++) {
      var bits = new BitArray(new byte[] { data[i] });
      var invertedBits = new BitArray(bits.Count);
      int x = 0;
      for (int p = bits.Count - 1; p >= 0; p--) {
         invertedBits[x] = bits[p];
         x++;
      }
      invertedBits.CopyTo(result, i);
   }
   return result;
}

編集:
バイト配列のエンディアンを変更するメソッドは次のとおりです。

static byte[] ConvertEndianness(byte[] data, int wordSize) {
    if (data.Length % wordSize != 0) throw new ArgumentException("The data length does not divide into an even number of words.");
    byte[] result = new byte[data.Length];
    int offset = wordSize - 1;
    for (int i = 0; i < data.Length; i++) {
        result[i + offset] = data[i];
        offset -= 2;
        if (offset < -wordSize) {
            offset += wordSize * 2;
        }
    }
    return result;
}

例:

byte[] data = { 1,2,3,4,5,6 };
byte[] inverted = ConvertEndianness(data, 2);
Console.WriteLine(BitConverter.ToString(inverted));

出力:

02-01-04-03-06-05

2 番目のパラメーターはワード サイズです。エンディアンは単語内のバイトの順序であるため、単語の大きさを指定する必要があります。

編集2:
ビットを逆にするためのより効率的な方法は次のとおりです。

static byte[] ReverseBits(byte[] data) {
    byte[] result = new byte[data.Length];
    for (int i = 0; i < data.Length; i++) {
        int b = data[i];
        int r = 0;
        for (int j = 0; j < 8; j++) {
            r <<= 1;
            r |= b & 1;
            b >>= 1;
        }
        result[i] = (byte)r;
    }
    return result;
}
于 2009-03-09T20:02:05.017 に答える
0

私が目にする大きな問題の1つは、ToBigdata[]が渡される配列の内容を変更することです。

、という名前の配列でToBigを呼び出しdata、その結果をに割り当ててinvertedいますが、ToBig内に新しい配列を作成しなかったため、両方の配列を変更し、実際にはそうではないのに、配列を異なるものとして扱いdataますinverted。 。

于 2009-03-09T19:53:22.683 に答える