36

ファイルから読み取ったバイト配列がメモリ内にあります。新しいバイト配列を作成して一度に各バイトをコピーするだけでなく、特定のポイント(インデックス)でバイト配列を分割して、操作のメモリフットプリントを増やしたいと思います。私が欲しいのは次のようなものです:

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

smallPortion1,2,3,4
largeBytesに等しい 5,6,7,8,9に等しい

4

8 に答える 8

25

Linq を使用した C# では、次のことができます。

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

;)

于 2011-02-20T12:45:32.250 に答える
22

FYI. System.ArraySegment<T> structure basically is the same thing as ArrayView<T> in the code above. You can use this out-of-the-box structure in the same way, if you'd like.

于 2009-11-02T16:58:08.550 に答える
15

これは私がそれをする方法です:

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();
    }
}
于 2008-08-21T19:47:39.070 に答える
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;
        }
    }
于 2012-11-01T11:56:26.560 に答える
1

意味がわかりません:

新しいバイト配列を作成して各バイトを一度にコピーすることなく、特定のポイント(インデックス)でバイト配列を分割し、操作のメモリ内フットプリントを増やしたいと思います。

ほとんどの言語、確かにC#では、配列が割り当てられると、そのサイズを変更する方法はありません。配列の長さを変更する方法を探しているようですが、それはできません。また、配列の2番目の部分のメモリを何らかの方法でリサイクルして、2番目の配列を作成する必要がありますが、これも実行できません。

要約すると、新しいアレイを作成するだけです。

于 2008-08-21T19:59:12.397 に答える
0

できません。あなたが望むのは、開始点とアイテムの数を維持することです。本質的に、イテレータを構築します。これがC++の場合はstd::vector<int>、組み込みのものをそのまま使用できます。

C# では、開始インデックス、カウント、および実装を保持する小さな反復子クラスを構築しますIEnumerable<>

于 2008-08-21T19:09:13.173 に答える
0

さまざまなアルゴリズムを試しました:

  • Skip().Take() => 断然最悪
  • Array.Copy
  • 配列セグメント
  • 新しい Guid(int, int16, int16 ...)

最新のものは、私が現在この拡張メソッドを使用している最速のものです:

        public static Guid ToGuid(this byte[] byteArray, int offset)
        {
            return new Guid(BitConverter.ToInt32(byteArray, offset), BitConverter.ToInt16(byteArray, offset + 4), BitConverter.ToInt16(byteArray, offset + 6), byteArray[offset + 8], byteArray[offset + 9], byteArray[offset + 10], byteArray[offset + 11], byteArray[offset + 12], byteArray[offset + 13], byteArray[offset + 14], byteArray[offset + 15]);
        }

10000000 GUID のバイト配列の場合:

Done (Skip().Take()) in 1,156ms (for only 100000 guids :))
Done (Array.Copy) in 1,219ms
Done (ToGuid extension) in 994ms
Done (ArraySegment) in 2,411ms
于 2021-02-27T21:43:57.720 に答える