2010-11-14 38 views
42

. Net'in bir bayt dizisine dönüştürmek için kullanabileceği bir tür kolay dönüştürme yöntemi olduğunu düşündüm. Ben hızlı bir arama yaptım ve tüm çözümler "iyi ol gün" gibi bir seferde bir bayt maskeleme/kaydırma vardır. Bir yerde ToByteArray() yöntemi yok mu?A'dan Z'ye bayt dizisi

cevap

69
byte[] bytes = BitConverter.GetBytes(i); 

notu rağmen ayrıca o etrafında hangi yolu ortaya çıkacaktı görmek için BitConverter.IsLittleEndian kontrol etmek isteyebilirsiniz! Tekrar tekrar bu yapıyoruz eğer, ya unsafe kodu kullanarak ya vardiya işlemleri (>>/<<) üzerinden kendiniz yazarak tüm bu kısa ömürlü dizisi tahsisleri önlemek isteyebileceği

Not. Vardiya işlemleri ayrıca platformunuzun endianitesinden etkilenmeme avantajına sahiptir; Eğer hep beklemediğiniz sırayla bayt olsun.

+2

+1: Açıklık açısından, "[...]" büyük-endian "ile" onları beklediğiniz sırada "yerine koyuyorum. – Ani

+0

Neden 'BitConverter.GetBytes (250)' '[250,0,0,0]' döndürür ve '[250]' değil? 'Byte.MaxValue == 255', değil mi? 4 byte ve CPU little-endian, öyleyse siz - –

+0

@Tobi aradığınız çünkü GetBytes (int). GetBytes (byte) yönteminde bir amaç olmaz. –

28

Marc'ın cevabı elbette doğru cevaptır. Ancak, vardiyalı operatörleri ve güvensiz kodu alternatif olarak belirttiği için. Daha az yaygın bir alternatifi paylaşmak istiyorum. düzeniyle bir yapı kullanma. Bu prensip olarak bir C/C++ union'a benzer.

Burada, Int32 veri türünün bileşen baytlarına ulaşmak için kullanılabilecek bir yapı örneği ve güzel olan iki yol olduğu, bayt değerlerini değiştirebildiğiniz ve Int . Eğer seri halinde yukarıda şimdi olarak kullanılabilir

using System.Runtime.InteropServices; 

    [StructLayout(LayoutKind.Explicit)] 
    struct Int32Converter 
    { 
    [FieldOffset(0)] public int Value; 
    [FieldOffset(0)] public byte Byte1; 
    [FieldOffset(1)] public byte Byte2; 
    [FieldOffset(2)] public byte Byte3; 
    [FieldOffset(3)] public byte Byte4; 

    public Int32Converter(int value) 
    { 
     Byte1 = Byte2 = Byte3 = Byte4 = 0; 
     Value = value; 
    } 

    public static implicit operator Int32(Int32Converter value) 
    { 
     return value.Value; 
    } 

    public static implicit operator Int32Converter(int value) 
    { 
     return new Int32Converter(value); 
    } 
    } 

Tabii

Int32Converter i32 = 256; 
Console.WriteLine(i32.Byte1); 
Console.WriteLine(i32.Byte2); 
Console.WriteLine(i32.Byte3); 
Console.WriteLine(i32.Byte4); 

i32.Byte2 = 2; 
Console.WriteLine(i32.Value); 

değişmezlik polisi geçtiğimiz olasılıkları :)

+0

+ 1: Bu güzel bir yaklaşım. Değişkenlik polisi için endişeleniyorsanız, alanları özel hale getirebilir ve bunları yalnızca özelliklerle gösterebilirsiniz. – Ani

+0

@Ani, Teşekkürler, bu byte üyeleri özel yapmak ve get-only özellikleri oluşturmak için iyi bir fikirdir. –

+0

'Byte1 = Byte2 = Byte3 = Byte4 = 0;' ifadesi. Sonraki Değer ataması, bunların üzerine yazdıkça gereksizdir. Bu, derleyici optimizasyon yazarları somunlarını yönlendiren tam olarak bir tür takma addır. Birlik, çoklu yazışmaları bellek kanalı üzerinden tek bir noktaya daralttığından zariftir. Yapıyı kullanmak, çok sık durumlar için dizi ayırmayı da engeller. – Pekka

2

Bu OT olabilir ama heyecan olmayabilir aşağıdaki Bir çok ilkel tip veya POD yapısı, Google Protocol Buffers for .Net sizin için yararlı olabilir. Bu, diğer kullanışlı özelliklerin yanı sıra yukarıda yükseltilen @Marc'e de değiniyor.

0

burada cevapların çoğu 'güvensiz" ya da değil littleEndian güvenli alınarak belirlenir. BitConverter güvenli littleEndian değildir. Yani basitçe okuyarak bir littleEndian güvenli versiyonu yapılmış (PZahra tarafından yazılan bakınız) here bir örnek üzerinde inşa .

bayt dizisi girdi tam hex olan
True 
0xDCBAABCDFFFE1608 

01: ters bayt dizisi BitConverter.IsLittleEndian ==

void Main(){  
    Console.WriteLine(BitConverter.IsLittleEndian); 
    byte[] bytes = BitConverter.GetBytes(0xdcbaabcdfffe1608); 
    //Console.WriteLine(bytes); 
    string hexStr = ByteArrayToHex(bytes); 
    Console.WriteLine(hexStr); 
} 

public static string ByteArrayToHex(byte[] data) 
{ 
    char[] c = new char[data.Length * 2]; 
    byte b; 
    if(BitConverter.IsLittleEndian) 
    { 
     //read the byte array in reverse 
     for (int y = data.Length -1, x = 0; y >= 0; --y, ++x) 
     { 
      b = ((byte)(data[y] >> 4)); 
      c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
      b = ((byte)(data[y] & 0xF)); 
      c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
     }    
    } 
    else 
    { 
     for (int y = 0, x = 0; y < data.Length; ++y, ++x) 
     { 
      b = ((byte)(data[y] >> 4)); 
      c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
      b = ((byte)(data[y] & 0xF)); 
      c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30); 
     } 
    } 
    return String.Concat("0x",new string(c)); 
} 

doğru Bu döndüğünde

+0

bir int olsa da. Bahsetmemek gerekirse, _read_'deki bu endianness kontrolünü yapmak çok daha mantıklıdır, dolayısıyla verilerinizin dizideki gibi olduğundan eminsiniz. – Nyerguds

İlgili konular