tags:

views:

7962

answers:

7

Howdy,

I have a byte array in memory, read from a file. I would like to split the byte array at a certain point(index) without having to just create a new byte array and copy each byte at a time, increasing the in memory foot print of the operation. What I would like is something like this:

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

smallPortion would equal 1,2,3,4
largeBytes would equal 5,6,7,8,9

Thank you, Keith

EDIT: @Michael, Nice code..

I see how this example works, by just creating specific "views" of the original array.

Just a few FYI questions for others who may read this later.

How would you see this working when passing the resultant view to other classes for use? How does the reference to the original array stay in scope?

I guess since you would actually be passing references to the "views", the other classes will continue to access the view in the same manner as the example in your Main. The View contains a private reference to the original array keeping in in scope and would not be GC'ed.

I think this is the answer.

Thank you, Keith

BTW, I love this site!

A: 

Keith can you retag with the language please :)

ta muchly.

EDIT: Thanks mate, you're much more likely to hit the correct buttons with people now :)

sparkes
+1  A: 

You can't. What you might want is keep a starting point and number of items; in essence, build iterators. If this is C++, you can just use std::vector and use the built-in ones.

In C#, I'd build a small iterator class that holds start index, count and implements IEnumerable<>.

Stu
+3  A: 

This is how I would do that:

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

        System.Collections.IEnumerator System.Collections.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();
        }
    }
Michał Piaskowski
+1  A: 

I'm not sure what you mean by:

I would like to split the byte array at a certain point(index) without having to just create a new byte array and copy each byte at a time, increasing the in memory foot print of the operation.

In most languages, certainly C#, once an array has been allocated, there is no way to change the size of it. It sounds like you're looking for a way to change the length of an array, which you can't. You also want to somehow recycle the memory for the second part of the array, to create a second array, which you also can't do.

In summary: just create a new array.

Outlaw Programmer
+4  A: 

Here is a simple way:

private static void splitByteArray(byte[] source, out byte[] first, out byte[] second, int lengthOfFirst)
{
    first = new byte[lengthOfFirst];
    second = new byte[source.Length - lengthOfFirst];
    Array.Copy(source, 0, first, 0, lengthOfFirst);
    Array.Copy(source, lengthOfFirst, second, 0, source.Length - lengthOfFirst);
}
Mike Polen
While your answer would split the array, I think it would end up making a duplicate copy of the array pieces using extra memory.
Keith Sirmons
A: 

In most languages, certainly C#, once an array has been allocated, there is no way to change the size of it. It sounds like you're looking for a way to change the length of an array, which you can't. You also want to somehow recycle the memory for the second part of the array, to create a second array, which you also can't do.

He wants to use the same memory for two smaller arrays. This means that if you modify values in the original array the values in new arrays will also change. In C you would just use pointers, pointing at different parts of the original array.

Michał Piaskowski
+3  A: 

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

Eren Ersonmez
Interesting. Too bad I didn't see this one when I was working on that project. Thanks for the info anyway.
Keith Sirmons