2009-03-09 13 views
0

仮定:バイトでビットを反転すると、次の出力が得られるのはなぜですか?

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

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

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 

何らかの理由でt 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は、ピクセルの第1の行を表す。 バイト32から第63バイトの第2行。

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

だからが混乱左ている:P

+0

FYI、エンディアンバイトのワードではなくビットのバイトの順序を指します。 – Michael

答えて

2

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

通常は、コンピューティングプラットフォーム間の変換に使用されます。ほとんどのCPUベンダー(現在)は、異なるチップセットに対して同じビット順序を使用しますが、異なるバイト順序を使用します。これにより、1つのシステムから別のものに2バイトの整数を渡している場合は、あなただけではビットを残す、ということを意味しますが、スワップバイト1および2、すなわち:

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

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

http://en.wikipedia.org/wiki/Endianness


あなたToBig方法は、バグがあります。情報の常に偉大な源 -

私はWikipediaで、この上に読むことをお勧めします。終わり

:あなたは、あなたの入力データをリセットしているので、あなたが反転両方の配列を受け取っている

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

invertedBits.CopyTo(data, i); 
} 

return data; 

あなたはにそれを変更する必要があります。問題は、配列が参照型であるため、元のデータを変更できることです。

+0

私はコードを更新しました...結果は同じですが、残念です – TimothyP

+0

ああ、お元気ですかではありません – TimothyP

+0

これはうまく動作しますが、私は間違っています。ビットの代わりにバイト? – TimothyP

6

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

ToBig()関数は、ビットスワップされたデータではなくオリジナルのデータを返しています。

0

ToBigは、渡されたdata[]配列の内容を変更します。

あなたはその後、invertedに結果を割り当て、dataという名前の配列にToBigを呼んでいるが、あなたはToBig内に新しい配列を作成しなかったので、あなたは、あなたが配列datainvertedの治療に進み、両方のアレイを修正実際にはそうではない場合とは異なります。

+0

私はちょうどそのコードを更新しましょう – TimothyP

2

すでにgreyfadeが言っているように、エンディアンはビットオーダーではありません。

あなたのコードが期待したことをしないのは、ToBigメソッドが送信する配列を変更するためです。つまり、メソッドを呼び出した後、配列は逆になり、datainvertedは、同じ配列を指す2つの参照に過ぎません。

ここに、修正されたバージョンのメソッドがあります。

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; 
} 
関連する問題