Как разбить массив байтов

У меня есть байтовый массив в памяти, прочитанный из файла. Я хотел бы разделить массив байтов в определенной точке (индекс) без необходимости просто создавать новый массив байтов и копировать каждый байт за раз, увеличивая отпечаток операции в памяти. То, что я хотел бы, что-то вроде этого:

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

21.08.2008 19:01:28
7 ОТВЕТОВ
РЕШЕНИЕ

Вот как я бы это сделал:

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();
    }
}
15
29.03.2016 10:17:21

Ты не можешь То, что вы могли бы хотеть, это сохранить отправную точку и количество предметов; по сути, строить итераторы. Если это C ++, вы можете просто использовать std::vector<int>и использовать встроенные.

В C # я бы создал небольшой класс итераторов, который содержит начальный индекс, число и реализации IEnumerable<>.

0
18.06.2017 12:35:14

Я не уверен, что вы подразумеваете под:

Я хотел бы разделить массив байтов в определенной точке (индекс) без необходимости просто создавать новый массив байтов и копировать каждый байт за раз, увеличивая отпечаток операции в памяти.

В большинстве языков, особенно в C #, после выделения массива невозможно изменить его размер. Похоже, вы ищете способ изменить длину массива, что вы не можете. Вы также хотите как-то перезапустить память для второй части массива, чтобы создать второй массив, чего вы также не можете сделать.

В итоге: просто создайте новый массив.

1
21.08.2008 19:59:12

FYI. System.ArraySegment<T>Структура в основном такая же, как ArrayView<T>в коде выше. Вы можете использовать эту готовую структуру таким же образом, если хотите.

20
18.02.2012 10:51:43
Интересно. Жаль, что я не видел этого, когда работал над этим проектом. Спасибо за информацию в любом случае.
Keith Sirmons 2.11.2009 17:23:10

В C # с Linq вы можете сделать это:

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

;)

20
20.02.2011 12:45:32
Оператор интересуется, как это сделать, не создавая [...] новый байтовый массив и копируя каждый байт за раз. Но это именно то, что делает ваш код LINQ. Дважды.
Christian Klauser 21.12.2011 22:00:56
..это помогло мне решить проблему, которая у меня не была решена ArraySegment<T>..
AceMark 18.03.2012 15:19:46
@Christian, чтобы избежать использования дополнительной памяти, просто удалите оба вызова .ToArray (). Это вернет два IEnumerable с гораздо меньшим количеством строк кода.
Gerardo Grignoli 12.07.2012 19:27:51
@GerardoGrignoli верно, но это дает вам IEnumerable<byte>. Хотя вполне безопасно (и быстро) многократно повторять это перечисляемое число, есть два недостатка: а) вы все равно не можете напрямую индексировать этот раздел массива. Конечно, реализации LINQ Skip / Take используют преимущества структуры массива, но они делают это, пытаясь привести IEnumerable к Collection или Array. б) После того, как вы вернете IEnumerable из вашего API, клиентам больше не гарантируется (системой типов), что перечисляемый код безопасен и эффективен для многократного повторения.
Christian Klauser 12.07.2012 20:24:15

Попробуй это:

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;
        }
    }
3
1.11.2012 11:56:26
Я думаю, что это должно быть статичным
Erçin Dedeoğlu 10.08.2017 07:14:33

Как сказал Эрен , вы можете использовать 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);
    }
}
0
9.06.2017 19:41:12