2010-03-27 35 views
6

Làm cách nào để loại bỏ một số byte khỏi mảng byte?Xóa 16 byte đầu tiên?

+4

Một câu hỏi SO thiếu sót khác, chúng tôi đã nhận được nhiều câu hỏi gần đây. Phân biệt bởi một câu hỏi duy nhất mà không làm gì nhiều để giải thích tiêu đề. Đến nay cách tiếp cận tốt nhất là không làm điều đó.Nhiều phương thức lấy một mảng có quá tải mất một độ dài và độ dài. Thậm chí còn có một lớp dành riêng cho nó: ArraySegment . Cho dù điều đó sẽ giúp bạn là khá rõ ràng từ câu hỏi của bạn. Chắc là không. –

Trả lời

24

EDIT: Như bình luận nobugz (và câu trả lời Reed Copsey của) đề cập, nếu bạn không thực sự cần kết quả như một mảng byte, bạn nên xem xét sử dụng ArraySegment<T>:

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

Nếu không, sao chép sẽ cần thiết - mảng luôn có kích thước cố định, vì vậy bạn không thể "xóa" 16 byte đầu tiên khỏi mảng hiện có. Thay vào đó, bạn sẽ phải tạo một mảng mới, nhỏ hơn và sao chép dữ liệu có liên quan vào đó.

gợi ý Zach là dọc theo dòng phù hợp với cách tiếp cận phi LINQ, nhưng nó có thể được thực hiện đơn giản hơn (điều này giả định bạn đã biết các mảng ban đầu có chiều dài ít nhất là 16 byte):

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

hoặc

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

tôi nghi ngờBuffer.BlockCopy sẽ nhanh hơn một chút, nhưng tôi không biết chắc chắn. Lưu ý rằng cả hai cách này có thể hiệu quả hơn đáng kể so với phương pháp LINQ nếu các mảng có liên quan lớn: phương pháp LINQ yêu cầu mỗi byte được trả về riêng lẻ từ một trình lặp và các bản sao trung gian có thể được thực hiện (trong cùng một cách thêm các mục vào List<T> cần phải phát triển mảng sao lưu theo định kỳ). Rõ ràng là không tối ưu hóa vi mô, nhưng nó có giá trị kiểm tra nếu bit mã này là một nút cổ chai hiệu suất.

EDIT: Tôi đã chạy một điểm chuẩn "nhanh chóng và bẩn" của ba phương pháp tiếp cận. Tôi không tin tưởng điểm chuẩn để phân biệt giữa Buffer.BlockCopyArray.Copy - chúng khá gần - nhưng cách tiếp cận LINQ chậm hơn 100 lần.

Trên máy tính xách tay của tôi, sử dụng mảng byte 10.000 phần tử, mất gần 10 giây để thực hiện 40.000 bản sao bằng LINQ; các phương pháp trên mất khoảng 80ms để thực hiện cùng một lượng công việc. Tôi tăng số lần lặp lên 4.000.000 và nó vẫn chỉ mất khoảng 7 giây. Rõ ràng là những lời khuyên thông thường xung quanh các tiêu chí vi chuẩn được áp dụng, nhưng đây là một sự khác biệt khá có ý nghĩa.

Chắc chắn sử dụng phương pháp trên nếu điều này là trong một con đường mã đó là quan trọng đối với hiệu suất :)

+0

+1, bộ đệm chắc chắn hiệu quả hơn đối với mảng lớn. –

+0

Sự khác biệt giữa Buffer.BlockCopy và Array.Copy khi được sử dụng với mảng byte là gì? – dtb

+0

@dtb: Tôi không mong đợi có bất kỳ sự khác biệt chức năng nào trong trường hợp này. 'Buffer.BlockCopy' hơi hạn chế hơn một chút - tôi nghi ngờ nó được cài đặt ở mức độ thấp hơn, nhưng tôi không biết chi tiết. –

14

Bạn có thể làm điều này:

using System.Linq 

// ... 

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

Nếu bạn không thể sử dụng LINQ, bạn có thể làm theo cách này:

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 

Bạn cũng sẽ cần phải xử lý các trường hợp mảng dài hơn 16 byte.

6

tôi cũng sẽ đề cập đến - tùy thuộc vào cách bạn định sử dụng các kết quả, thường xuyên, một cách tiếp cận khác là sử dụng ArraySegment<T> để chỉ truy cập phần còn lại của mảng. Điều này ngăn sự cần thiết phải sao chép mảng, có thể hiệu quả hơn trong một số trường hợp sử dụng:

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

// Use segment how you'd use your array... 
Các vấn đề liên quan