2008-08-21 7 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

FYI. 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); 
    } 
}