2008-08-21 121 views
26

我在內存中有一個字節數組,從文件中讀取。我想在某個點(索引)分割字節數組,而不必創建一個新的字節數組並一次複製每個字節,從而增加了操作的內存足跡。我想是這樣的:如何分割字節數組

byte[] largeBytes = [1,2,3,4,5,6,7,8,9]; 
byte[] smallPortion; 
smallPortion = split(largeBytes, 3); 

smallPortion就等於1,2,3,4
largeBytes就等於5,6,7,8,9

回答

14

這是我會怎麼做:

using System; 
using System.Collections; 
using System.Collections.Generic; 

class ArrayView<T> : IEnumerable<T> 
{ 
    private readonly T[] array; 
    private readonly int offset, count; 

    public ArrayView(T[] array, int offset, int count) 
    { 
     this.array = array; 
     this.offset = offset; 
     this.count = count; 
    } 

    public int Length 
    { 
     get { return count; } 
    } 

    public T this[int index] 
    { 
     get 
     { 
      if (index < 0 || index >= this.count) 
       throw new IndexOutOfRangeException(); 
      else 
       return this.array[offset + index]; 
     } 
     set 
     { 
      if (index < 0 || index >= this.count) 
       throw new IndexOutOfRangeException(); 
      else 
       this.array[offset + index] = value; 
     } 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     for (int i = offset; i < offset + count; i++) 
      yield return array[i]; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     IEnumerator<T> enumerator = this.GetEnumerator(); 
     while (enumerator.MoveNext()) 
     { 
      yield return enumerator.Current; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     byte[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 
     ArrayView<byte> p1 = new ArrayView<byte>(arr, 0, 5); 
     ArrayView<byte> p2 = new ArrayView<byte>(arr, 5, 5); 
     Console.WriteLine("First array:"); 
     foreach (byte b in p1) 
     { 
      Console.Write(b); 
     } 
     Console.Write("\n"); 
     Console.WriteLine("Second array:"); 
     foreach (byte b in p2) 
     { 
      Console.Write(b); 
     } 
     Console.ReadKey(); 
    } 
} 
0

你不能。你可能想要的是保持一個起點和數量的項目;本質上來說,構建迭代器。如果這是C++,則可以使用std::vector<int>並使用內置的。在C#中,我會構建一個小的迭代器類,它包含開始索引,計數並實現IEnumerable<>

1

我不知道你的意思是:

我想字節數組在某一點分裂(指數)而不必創建一個新的字節數組並一次複製每個字節,從而增加了操作的內存佔用量。

在大多數語言中,肯定是C#,一旦數組被分配,就沒有辦法改變它的大小。這聽起來像你正在尋找一種方法來改變數組的長度,你不能。你也想以某種方式回收數組第二部分的內存,以創建第二個數組,這也是你無法做到的。

總結:只需創建一個新的數組。

17

僅供參考。 System.ArraySegment<T>結構基本上與上面的代碼中的ArrayView<T>是一樣的。如果你願意,你可以用相同的方式使用這個開箱即用的結構。

+0

有趣。太糟糕了,我在做這個項目時沒有看到這個。無論如何感謝您的信息。 – 2009-11-02 17:23:10

13

在C#中使用LINQ,你可以這樣做:

smallPortion = largeBytes.Take(4).ToArray(); 
largeBytes = largeBytes.Skip(4).Take(5).ToArray(); 

;)

+3

該OP想知道如何做到這一點**,而不必創建一個新的字節數組,並一次複製每個字節**但這正是你的LINQ代碼所做的。兩次。 – 2011-12-21 22:00:56

+0

..這幫助我解決了一個我沒有通過`ArraySegment `得到的問題.. .. – AceMark 2012-03-18 15:19:46

3

試試這個:

private IEnumerable<byte[]> ArraySplit(byte[] bArray, int intBufforLengt) 
    { 
     int bArrayLenght = bArray.Length; 
     byte[] bReturn = null; 

     int i = 0; 
     for (; bArrayLenght > (i + 1) * intBufforLengt; i++) 
     { 
      bReturn = new byte[intBufforLengt]; 
      Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLengt); 
      yield return bReturn; 
     } 

     int intBufforLeft = bArrayLenght - i * intBufforLengt; 
     if (intBufforLeft > 0) 
     { 
      bReturn = new byte[intBufforLeft]; 
      Array.Copy(bArray, i * intBufforLengt, bReturn, 0, intBufforLeft); 
      yield return bReturn; 
     } 
    } 
0

由於Eren said,你可以使用ArraySegment<T>。以下是擴展方法和用法示例:

public static class ArrayExtensionMethods 
{ 
    public static ArraySegment<T> GetSegment<T>(this T[] arr, int offset, int? count = null) 
    { 
     if (count == null) { count = arr.Length - offset; } 
     return new ArraySegment<T>(arr, offset, count.Value); 
    } 
} 

void Main() 
{ 
    byte[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 
    var p1 = arr.GetSegment(0, 5); 
    var p2 = arr.GetSegment(5); 
    Console.WriteLine("First array:"); 
    foreach (byte b in p1) 
    { 
     Console.Write(b); 
    } 
    Console.Write("\n"); 
    Console.WriteLine("Second array:"); 
    foreach (byte b in p2) 
    { 
     Console.Write(b); 
    } 
}