C # - преобразование uint в byte []

Итак, я использовал BitConverter.GetBytes () для преобразования uint32 в byte [], но мой порядок в массиве кажется обратным. http://msdn.microsoft.com/en-us/library/1184xdy4.aspx (показывает, что байт [] выглядит с прямым порядком байтов).

Есть ли лучший способ справиться с этим, чем просто использовать linq для изменения байтовых массивов?


person Joel Barsotti    schedule 03.08.2010    source источник
comment
Я предполагаю, что здесь я запутался, поскольку BitConverter.IsLittleEndian возвращает false, но BitConverter.GetBytes () возвращает массивы с прямым порядком байтов.   -  person Joel Barsotti    schedule 03.08.2010
comment
Если это Windows, BitConverter.IsLittleEndian, возвращающий false, явно является ошибкой, поскольку процессоры x86 и x86-64 имеют Little Endian.   -  person Powerlord    schedule 05.08.2010


Ответы (5)


Array.Reverse, чтобы изменить порядок байтов.

person leppie    schedule 03.08.2010

Если вы собираетесь перемещаться между архитектурами платформы, простое реверсирование массива может быть правильным на одной платформе, но не удастся на платформе, которая уже использует обратный порядок байтов.

Вы используете функции IPAddress.HostToNetworkOrder, что гарантирует, что данные всегда будут в сетевом порядке (с прямым порядком байтов).

uint number = 234234233;
uint bigEndian = (uint)IPAddress.HostToNetworkOrder((int)number);
byte[] b = BitConverter.GetBytes(bigEndian);
person Chris Taylor    schedule 03.08.2010
comment
Спасибо. Это быстрее, чем Array.Reverse. Но у меня были проблемы с типами, пока я не писал такой код: var buffer = BitConverter.GetBytes ((uint) IPAddress.HostToNetworkOrder ((int) i)); - person Geograph; 21.07.2018
comment
@ Географ, какие у тебя проблемы? Возможно, для этого стоит создать специальный вопрос, чтобы вы могли предоставить более полный пример и детали. - person Chris Taylor; 21.07.2018
comment
Ваш исходный пример не может быть скомпилирован с ошибкой CS0266. Невозможно неявно преобразовать тип long в uint. Существует явное преобразование (вам не хватает приведения?) - person Geograph; 22.07.2018
comment
@ Географ, понятно. Да, чтобы это работало правильно, вам нужно будет преобразовать число в int, чтобы получить результат размера int. Буду обновлять образец, спасибо. - person Chris Taylor; 23.07.2018

Microsoft обсуждает проблему прямого / обратного порядка байтов с помощью метода GetBytes () на странице документации для BitConverter.

person C8H10N4O2    schedule 03.08.2010

Итак, я понял, что большая часть моего замешательства связана с этим: Поле IsLittleEndian сообщает ложное значение, но оно должно быть Little-Endian?

В итоге я обернул все вызовы BitConverter вызовом, который принял дополнительный параметр для указания порядка байтов, а затем добавил функцию, которая вызывается для проверки, нужно ли уважать байты.

public static class BitEndianConverter
{
    public static byte[] GetBytes(bool value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }

    public static byte[] GetBytes(char value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(double value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(float value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(int value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(long value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(short value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(uint value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(ulong value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }
    public static byte[] GetBytes(ushort value, bool littleEndian)
    {
        return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
    }

    private static byte[] ReverseAsNeeded(byte[] bytes, bool wantsLittleEndian)
    {
        if (wantsLittleEndian == BitConverter.IsLittleEndian)
            return bytes;
        else
            return (byte[])bytes.Reverse().ToArray();
    }
}
person Joel Barsotti    schedule 05.08.2010
comment
Я скопировал этот класс, он работает хорошо, более интуитивно понятен и удобочитаем, чем другие решения. Мне было интересно, имеет ли это смысл или можно ли сделать GetBytes общим? что-то вроде общедоступного статического байта [] GetBytes ‹T› (значение T, bool littleEndian) ... - person shelbypereira; 17.09.2020

Ниже приведен способ быстрого получения массива байтов с прямым порядком байтов.

    public static byte[] GetBigEndianBytes(UInt32 val, bool isLittleEndian)
    {
        UInt32 bigEndian = val;
        if (isLittleEndian)
        {
            bigEndian = (val & 0x000000FFU) << 24 | (val & 0x0000FF00U) << 8 |
                 (val & 0x00FF0000U) >> 8 | (val & 0xFF000000U) >> 24;
        }
        return BitConverter.GetBytes(bigEndian);
    }

Эта перегрузка может быть удобной, хотя следует проявлять осторожность при работе на разных машинах с разными порядками байтов.

    public static byte[] GetBigEndianBytes(UInt32 val)
    {
        return GetBigEndianBytes(val, BitConverter.IsLittleEndian);
    }
person bytefire    schedule 07.09.2013