Domanda

Ho un array di byte in memoria, letto da un file.Vorrei dividere l'array di byte a un certo punto (indice) senza dover semplicemente creare un nuovo array di byte e copiare ogni byte alla volta, aumentando l'impronta di memoria dell'operazione.Quello che vorrei è qualcosa del genere:

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

smallPortion equivarrebbe a 1,2,3,4
largeBytes equivarrebbe a 5,6,7,8,9

È stato utile?

Soluzione

Ecco come lo farei:

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();
    }
}

Altri suggerimenti

PER TUA INFORMAZIONE. System.ArraySegment<T> la struttura fondamentalmente è la stessa cosa di ArrayView<T> nel codice qui sopra.Puoi utilizzare questa struttura pronta all'uso allo stesso modo, se lo desideri.

In C# con Linq puoi fare questo:

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

;)

Prova questo:

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;
        }
    }

Non sono sicuro di cosa intendi con:

Vorrei dividere l'array di byte a un certo punto (indice) senza dover semplicemente creare un nuovo array di byte e copiare ogni byte alla volta, aumentando l'impronta di memoria dell'operazione.

Nella maggior parte dei linguaggi, sicuramente in C#, una volta allocato un array, non è possibile modificarne la dimensione.Sembra che tu stia cercando un modo per modificare la lunghezza di un array, cosa che non puoi.Vuoi anche riciclare in qualche modo la memoria per la seconda parte dell'array, per creare un secondo array, cosa che non puoi fare.

In sintesi:basta creare un nuovo array.

COME Ha detto Eren, Puoi usare ArraySegment<T>.Ecco un metodo di estensione e un esempio di utilizzo:

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

Non puoi.Ciò che potresti volere è mantenere un punto di partenza e un numero di elementi;in sostanza, costruisci iteratori.Se questo è C++, puoi semplicemente usare std::vector<int> e utilizzare quelli integrati.

In C#, creerei una piccola classe iteratore che contenga l'indice iniziale, il conteggio e le implementazioni IEnumerable<>.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top