Почему я получаю следующий вывод при инвертировании битов в байте? - PullRequest
0 голосов
/ 09 марта 2009

Предположение:

Преобразование byte [] от Little Endian до Big Endian означает инвертирование порядка битов в каждый байт байта [].

Предполагая, что это правильно, я попробовал следующее, чтобы понять это:

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 второй строки пикселей.

У меня есть код, который выводит эти биты ... но разработчик говорит мне они в неправильном порядке ... Он говорит, что байты в порядке, но биты нет.

Так что я запутался: p

Ответы [ 4 ]

6 голосов
/ 09 марта 2009

Нет. Порядковый номер относится к порядку байтов , а не бит. Системы с прямым порядком байтов хранят самые старшие байты первого, а системы с младшим порядком байтов хранят младшие старшие. Биты внутри байта остаются в том же порядке.

Кажется, ваша функция ToBig () возвращает исходные данные, а не битовые данные.

2 голосов
/ 09 марта 2009

Как уже говорилось в greyfade, порядковый номер - это не упорядочение битов.

Причина, по которой ваш код не выполняет то, что вы ожидаете, заключается в том, что метод ToBig изменяет массив, который вы ему отправляете. Это означает, что после вызова метода массив инвертируется, и 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;
}

Edit:
Вот метод, который изменяет порядковый номер байтового массива:

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:
Вот более эффективный метод обращения битов:

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;
}
2 голосов
/ 09 марта 2009

Ваш метод может быть правильным на данный момент. Существуют разные значения порядка байтов, и это зависит от аппаратного обеспечения.

Как правило, он используется для конвертации между вычислительными платформами. Большинство производителей процессоров (сейчас) используют одинаковый порядок следования битов, но разный порядок следования байтов для разных наборов микросхем. Это означает, что если вы передаете 2-байтовый тип int из одной системы в другую, вы оставляете биты в покое, но меняете местами байты 1 и 2, то есть:

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

Однако это не всегда так. Некоторое оборудование все еще использует инвертированный порядок битов, поэтому то, что у вас есть, может быть правильным. Вам нужно будет либо довериться своему аппаратному устройству. или посмотри дальше.

Я рекомендую прочитать об этом в Википедии - всегда отличный источник информации:

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


В вашем методе ToBig есть ошибка.

В конце:

 invertedBits.CopyTo(data, i);
}

return data;

Вам нужно изменить это на:

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

Вы сбрасываете свои входные данные, поэтому вы получаете инвертированные оба массива. Проблема в том, что массивы являются ссылочными типами, поэтому вы можете изменять исходные данные.

0 голосов
/ 09 марта 2009

Одна большая проблема, которую я вижу, состоит в том, что ToBig изменяет содержимое массива data[], который ему передается.

Вы вызываете ToBig для массива с именем data, затем присваиваете результат inverted, но поскольку вы не создали новый массив внутри ToBig, вы изменили оба массива, а затем приступили к обработке массивов. data и inverted отличаются друг от друга, когда на самом деле это не так.

...