Muszę przekonwertować plik int
na byte[]
jeden ze sposobów, aby to zrobić BitConverter.GetBytes()
. Ale nie jestem pewien, czy pasuje do następującej specyfikacji:
Liczba całkowita ze znakiem XDR to 32-bitowe dane, które kodują liczbę całkowitą z zakresu [-2147483648,2147483647]. Liczba całkowita jest reprezentowana w notacji z dopełnieniem do dwóch. Najbardziej i najmniej znaczące bajty to odpowiednio 0 i 3. Liczby całkowite są deklarowane w następujący sposób:
Źródło: RFC1014 3.2
Jak mogę dokonać transformacji int na bajt, która spełniłaby powyższą specyfikację?
c#
.net
bit-manipulation
nfs
Piotr
źródło
źródło
Odpowiedzi:
RFC próbuje po prostu powiedzieć, że liczba całkowita ze znakiem jest zwykłą 4-bajtową liczbą całkowitą z bajtami uporządkowanymi w sposób big-endian.
Teraz najprawdopodobniej pracujesz na maszynie little-endian i
BitConverter.GetBytes()
dasz cibyte[]
odwrotność. Możesz więc spróbować:Aby kod był najbardziej przenośny, możesz to zrobić w następujący sposób:
źródło
byte[] result = intBytes;
? czy nie jestintBytes
już tablicą, którą chcesz?result
jest zbędny w tym fragmencie kodu. Jednak czułem, że bardziej pedagogiczne było wyraźne pokazanie czytelnikowi, jaki był rezultat, niż założenie, że może on zorientować się, że wynik jest zawarty w jakiejś nazwanej zmiennejintBytes
. Poza tym wykonanie przypisania jest tanie, ponieważ nie kopiuje pamięci ani nie alokuje nowej pamięci, po prostu dodaje nową nazwę do już przydzielonej tablicy. Więc dlaczego tego nie zrobić?Oto inny sposób, aby to zrobić: jak wszyscy wiemy, 1x bajt = 8x bitów, a także „zwykła” liczba całkowita (int32) zawiera 32 bity (4 bajty). Możemy użyć operatora >>, aby przesunąć bity w prawo (operator >> nie zmienia wartości).
źródło
& 0xFF
bity są niepotrzebne.unchecked
blok. Obecnie działa tylko wtedy, gdy sprawdzanie przepełnienia liczb całkowitych jest wyłączone w ustawieniach kompilatora.BitConverter.GetBytes(int)
prawie robi, co chcesz, z wyjątkiem tego, że endianness jest zły.Możesz użyć metody IPAddress.HostToNetwork , aby zamienić bajty w wartości całkowitej przed użyciem
BitConverter.GetBytes
lub użyciem klasy EndianBitConverter Jona Skeeta . Obie metody są słuszne (tm) w zakresie przenośności.źródło
Kiedy patrzę na ten opis, mam wrażenie, że ta liczba całkowita xdr jest po prostu „standardową” liczbą całkowitą typu big-endian, ale jest wyrażona w najbardziej zaciemniony sposób. Notacja dopełniająca do dwóch jest lepiej znana jako U2 i właśnie tego używamy na dzisiejszych procesorach. Kolejność bajtów wskazuje, że jest to notacja big-endian .
Odpowiadając więc na twoje pytanie, powinieneś odwrócić elementy w swojej tablicy (0 <--> 3, 1 <--> 2), ponieważ są one zakodowane w little-endian. Aby się upewnić, najpierw sprawdź,
BitConverter.IsLittleEndian
na jakiej maszynie używasz.źródło
Dlaczego cały ten kod w przykładach powyżej ...
Struktura z jawnym układem działa w obie strony i nie ma wpływu na wydajność.
Aktualizacja: Ponieważ pojawia się pytanie, jak radzić sobie z endianizmem, dodałem interfejs, który ilustruje, jak to ująć. Inna struktura implementująca może zająć się odwrotnym przypadkiem
źródło
Jeśli chcesz uzyskać więcej ogólnych informacji na temat różnych metod przedstawiania liczb, w tym dopełnienia do dwóch, spójrz na:
Uzupełnienie do dwóch i podpisana reprezentacja numeru w Wikipedii
źródło
Innym sposobem jest użycie BinaryPrimitives w ten sposób
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
źródło
źródło
źródło
Int16
.