代码之家  ›  专栏  ›  技术社区  ›  Keith Sirmons

如何拆分字节数组

  •  29
  • Keith Sirmons  · 技术社区  · 16 年前

    我在内存中有一个字节数组,从一个文件中读取。我希望在某个点(索引)拆分字节数组,而不必创建一个新的字节数组,一次复制每个字节,从而增加操作的内存足迹。我想要这样的:

    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

    7 回复  |  直到 7 年前
        1
  •  14
  •   Jon Skeet    9 年前

    我就是这样做的:

    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();
        }
    }
    
        2
  •  20
  •   Eren Ersönmez    13 年前

    FYI。 System.ArraySegment<T> 结构基本上与 ArrayView<T> 在上面的代码中。如果您愿意的话,您可以用同样的方式使用这种开箱即用的结构。

        3
  •  18
  •   Alireza Naghizadeh    14 年前

    在C中,您可以使用LINQ执行以下操作:

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

    ;)

        4
  •  3
  •   Robert Wisniewski    12 年前

    试试这个:

    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;
            }
        }
    
        5
  •  1
  •   Tim Frey    16 年前

    我不知道你说的是什么意思:

    我希望在某个点(索引)拆分字节数组,而不必创建一个新的字节数组,一次复制每个字节,从而增加操作的内存足迹。

    在大多数语言中,当然是c,一旦分配了一个数组,就无法更改它的大小。听起来您正在寻找一种方法来更改数组的长度,但您不能这样做。您还希望以某种方式回收数组第二部分的内存,创建第二个数组,但您也不能这样做。

    总之:只需创建一个新数组。

        6
  •  0
  •   orad    7 年前

    AS 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);
        }
    }
    
        7
  •  0
  •   Donald Duck user7392049    7 年前

    你不能。你可能想要的是保持一个起点和项目的数量;本质上,构建迭代器。如果这是C++,你可以使用 std::vector<int> 使用内置的。

    在C中,我将构建一个小的迭代器类,它保存开始索引、计数和实现 IEnumerable<> .