2010-03-27 25 views
6

Bayt dizisinden birkaç bayt kaldırmaya nasıl giderim?İlk 16 Byte Kaldır?

+4

Bir başka kusurlu SO sorusu, son zamanlarda bunlardan çok şey alıyoruz. Başlığı açıklamak için fazla bir şey yapmayan tek bir cümle sorusuyla ayırt edilir. Şimdiye kadar en iyi yaklaşım bunu yapmamaktır.Bir dizi alan birçok yöntem bir ofset ve uzunluk alan bir aşırı yüklenmeye sahiptir. Bunun için özel bir sınıf bile var: ArraySegment . Bu size yardım edip etmeyeceği sorusundan belli değil. Muhtemelen değil. –

cevap

24

DÜZENLEME: nobugz en comment (ve Reed Copsey cevabı) bahseder gibi aslında bir bayt dizisi olarak sonucu gerekmiyorsa, sen ArraySegment<T> kullanarak içine görünmelidir:

Aksi
ArraySegment<byte> segment = new ArraySegment<byte>(full, 16, full.Length - 16); 

, kopyalama olacak gerekli - diziler her zaman sabit bir boyuta sahip olduğundan, var olan diziden ilk 16 baytı "kaldıramazsınız". Bunun yerine, yeni, daha küçük bir dizi oluşturup ilgili verileri ona kopyalamanız gerekir.

Zach'in öneri dışı LINQ yaklaşım için doğru çizgiler boyunca, ancak (bu zaten orijinal dizi uzun, en az 16 bayt olduğunu biliyorum varsayar) daha basit hale getirilebilir:

byte[] newArray = new byte[oldArray.Length - 16]; 
Buffer.BlockCopy(oldArray, 16, newArray, 0, newArray.Length); 

veya

byte[] newArray = new byte[oldArray.Length - 16]; 
Array.Copy(oldArray, 16, newArray, 0, newArray.Length); 

Ben şüpheliBuffer.BlockCopy biraz daha hızlı olacak, ama emin değiliz. İlgili dizileri büyükse, bunların her ikisi de LINQ yaklaşımından önemli ölçüde daha verimli olabilir: LINQ yaklaşımı, her baytın tek tek bir yineleyiciden döndürülmesini ve potansiyel olarak ara kopyaların yapılmasını gerektirir (aynı şekilde). List<T> ürününe öğe eklerken, yedekleme dizisini düzenli olarak büyütmek gerekir). Açıkçası, mikro-optimize etmeyin, ancak bu kod biraz performans darboğaz ise kontrol değer.

DÜZENLEME: Üç yaklaşımın çok "hızlı ve kirli" bir karşılaştırmasını yaptım. Ben Buffer.BlockCopy ve Array.Copy arasındaki farkı ayırt etmek için kıyaslama yapıyorum - oldukça yakındılar - ama LINQ yaklaşımı 100 kat daha yavaştı.

Dizüstü bilgisayarımda, 10,000 öğeden oluşan bayt dizileri kullanarak, LINQ kullanarak 40.000 kopya gerçekleştirmesi yaklaşık 10 saniye sürdü; Yukarıdaki yaklaşımlar aynı miktarda işi yapmak için yaklaşık 80 ms sürdü. Yinelemeyi 4,000,000'e çıkardım ve hala sadece 7 saniye sürdü. Açıkçası, mikro kriterler etrafında normal uyarılar geçerlidir, ancak bu oldukça anlamlı bir farktır. Bu performans :) önemlidir bir kod yolu ise

Kesinlikle yukarıdaki yaklaşım kullanmak

+0

+1, tamponlama büyük diziler için kesinlikle daha verimlidir. –

+0

Bayt dizileriyle kullanıldığında Buffer.BlockCopy ve Array.Copy arasındaki fark nedir? – dtb

+0

@dtb: Bu durumda herhangi bir işlevsel farklılık olmasını beklemiyorum. Buffer.BlockCopy 'biraz daha kısıtlayıcıdır - bunun daha düşük seviyeli bir şekilde uygulandığından şüpheleniyorum, ama detayları bilmiyorum. –

14

Bunu yapabilirsiniz: Eğer Linq kullanamıyorsanız

using System.Linq 

// ... 

var newArray = oldArray.Skip(numBytes).ToArray(); 
0

, bunu bu şekilde yapabilirsiniz:

byte[] myArray = // however you acquire the array 

byte[] newArray = new byte[myArray.Length - 16]; 

for (int i = 0; i < newArray.Length; i++) 
{ 
    newArray[i] = myArray[i + 16]; 
} 

// newArray is now myArray minus the first 16 bytes 

Ayrıca olaya el gerekir nerede dizisi 16 bayttan daha azdır.

6
Şunu da belirtmek edecek

- Sonuçları kullanmayı planlıyorsanız biçimine bağlı olarak, genellikle, alternatif bir yaklaşım kullanmaktır Dizinin kalan kısmına erişmek için ArraySegment<T>. Bu, bazı kullanım senaryolarında daha verimli olabilen dizinin kopyalanması ihtiyacını önler: