0

I am reading a .pst (File Structure) file byte by byte in a byte array, now i want to break the data into two parts like in even and odd, and store it in 2 other files one for even and one for odd . Below is the code that i am stuck at

        byte[] array = File.ReadAllBytes("PST_Sample.pst");
        for (int index = 0; index < even.Length; index++)
        {

            //Console.WriteLine(index + " : " + array[index]);
            if ((array[index] % 2) == 0)
            {
                even[index] = array[index];
            }
            else
            {
                odd[index] = array[index];
            }
        }

In FOR loop i have tried array.length, even.length nothing is working.

  • You are going to need 2 index's. One for where you are in the full array, and one to track where you are in the even/odd arrays. You will also want the for loop to go to array.length. – Michael Sharp Nov 14 '17 at 18:04
  • do you absolutely need your container to be an array? If not, you might want to consider a list instead. That way you could simply instanciate a new list and then add each values – Sirmyself Nov 14 '17 at 18:05
  • @Blake Thingstad Just solved the problem. Thanks anyways. – Hamza Shahid Nov 14 '17 at 18:55

5 Answers5

1

The array is two times longer than even and odd arrays.
Try the following code instead:

for (int index = 0; index < even.Length; index++)
{
    even[index] = array[index * 2];
    odd[index] = array[index * 2 + 1];
}
Dmitry
  • 13,797
  • 6
  • 32
  • 48
1

Increment the index in the source array by 2 and in the destination arrays by 1 only. This allows you to assign the bytes to odd and even arrays in one bunch without additional even/odd tests.

for (int src = 0, dst = 0; src < array.Length; src += 2, dst++)
{
    even[dst] = array[src];
    odd[dst] = array[src + 1];
}

If the array length is odd, then odd[] must be one shorter than even[]. Also, special care must be taken to avoid running into an index out of range exception.

A solution also working with odd array lengths and avoiding additional tests within the loop:

byte[] array = { 0, 1, 2, 3, 4 };
bool isOdd = array.Length % 2 == 1;

byte[] even = new byte[(array.Length + 1) / 2];
byte[] odd = new byte[array.Length / 2];

int length = isOdd ? array.Length - 1 : array.Length;
for (int src = 0, dst = 0; src < length; src += 2, dst++) {
    even[dst] = array[src];
    odd[dst] = array[src + 1];
}

if (isOdd) { // If array length is odd, the last index is even (= length - 1).
    // Assign the last remaining entry.
    even[even.Length - 1] = array[array.Length - 1];
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

Your test is wrong. You are testing the bytes in the data, not the index. It should be:

 for (int index = 0; index < array.Length; index++)
    {

        //Console.WriteLine(index + " : " + array[index]);
        if ((index % 2) == 0)
        {
            even[index/2] = array[index];
        }
        else
        {
            odd[(index - 1)/2] = array[index];
        }
    }
Jay Buckman
  • 581
  • 5
  • 18
  • 1
    This wont work. The length of the even and odd array is half the length of the full array. So when index is greater then the length of even or odd, this will fail. – Michael Sharp Nov 14 '17 at 18:06
  • Yes, of course - I just addressed the main problem. I'll edit my code. – Jay Buckman Nov 14 '17 at 18:09
0

If you are just looking for a solution and not necessarily how to fix your code, then the easiest thing is to just use LINQ.

byte[] array = new byte[] 
{
    55, 56, 57, 58, 89, 90, 91, 92
};
var even = array.Where((b, i) => i % 2 == 0);
var odd = array.Except(even);

If you need even and odd to be byte[] then just add .ToArray() to each line.

If you want to interleave these values back together then here is an extension method for that (remove static and this if you just want a normal method). I borrowed and modified this question's accepted answer to make it interleave even when one collection is larger than the other.

public static IEnumerable<T> Interleave<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
    using (var firstEnumerator = first.GetEnumerator())
    using (var secondEnumerator = second.GetEnumerator())
    {
        var firstMoved = firstEnumerator.MoveNext();
        var secondMoved = secondEnumerator.MoveNext();

        while (firstMoved || secondMoved)
        {
            if (firstMoved)
                yield return firstEnumerator.Current;
            if (secondMoved)
                yield return secondEnumerator.Current;

            firstMoved = firstEnumerator.MoveNext();
            secondMoved = secondEnumerator.MoveNext();
        }
    }
}
Blake Thingstad
  • 1,639
  • 2
  • 12
  • 19
  • your even variable is storing data that it should, but the odd variable file is still empty. – Hamza Shahid Nov 14 '17 at 18:38
  • yup, Thanks. one more thing, how can i combine two files data into single file, see my above code, i stored a single file data in even and odd files, now i want to recover that data again into single file. how can i do that? – Hamza Shahid Nov 14 '17 at 18:52
  • @HamzaShahid Are you wanting the bytes to be joined back together mixed together (even, odd, even odd, ...) or can they just be stuck together (even, even, even, ..., even, odd, odd, odd, ...)? – Blake Thingstad Nov 14 '17 at 18:55
  • mixed like even odd even odd. – Hamza Shahid Nov 14 '17 at 19:00
  • I am a bit confused about where would i load file even, odd files and where would a save my combined data into another file, can you specify that? – Hamza Shahid Nov 15 '17 at 12:29
  • @HamzaShahid You would do it the same way you already have it in your posted code. `File.ReadAllBytes("filename.pst")` and `File.WriteAllBytes("filename.pst", array);` Do ReadAllBytes twice for the even and odd files and then use Interleave on those arrays, then WriteAllBytes on the new array from Interleave. – Blake Thingstad Nov 15 '17 at 14:08
  • @HamzaShahid Glad I was able to help =) – Blake Thingstad Nov 15 '17 at 14:30
0

Your main array is twice as long as the resulting two. There might be 2 or 3 design errors in your code depending on what your data are

1rst flaw is that you use the same index for all the arrays at the same time. So you skip a memory cell on each pass of your for either for your even or your odd array and since your limit is the size of your even array, you only go halfway through your main array.

2nd flaw is that, depending of your data, you may need a different size for your even and odd array because if you have 46 odd numbers and 20 even numbers you still get your arrays size of 33 for each one

3rd flaw and probably most critical : combining the first and second flaw, you most certainly get an index out of bound exception. If you have 25 even number and 67 odd numbers, since you use the same index, your code will work until you get to index >= 25 where you will get an index out of bound, since even array has a last index of 32.

I would also suggest that you use lists instead of arrays since they are designed to store any number of data.

Here's how you could write your code to avoid those flaws :

byte[] array = File.ReadAllBytes("PST_Sample.pst");
List<byte> even = new List<byte>();
List<byte> odd = new List<byte>();

for (int index = 0; index < array.Length; index++)
{
    if ((array[index] % 2) == 0)
    {
        even.Add(array[index]);
    }
    else
    {
        odd.Add(array[index]);
    }
}

File.WriteAllBytes("even_file.pst", even.ToArray());
File.WriteAllBytes("odd_file.pst", odd.ToArray());
Sirmyself
  • 1,464
  • 1
  • 14
  • 29