4

I want to take data from an IP packet which is a byte array and split it into a collection of byte arrays that start with 0x47 i.e. mpeg-2 transport packets.

For example the original byte array looks like this:

08 FF FF 47 FF FF FF 47 FF FF 47 FF 47 FF FF FF FF 47 FF FF 

How would you split the byte array on 0x47 and retain the deliminator 0x47 so it looks like this? In order words an array of byte arrays that start on a particular hexadecimal?

[0] 08 FF FF
[1] 47 FF FF FF
[2] 47 FF FF
[3] 47 FF
[4] 47 FF FF FF FF
[5] 47 FF FF
1
  • Why not simply loop through that? That ought to work in like O(2n) time, I suppose. Commented Jun 24, 2016 at 19:50

4 Answers 4

4

You can easily implement the splitter required:

public static IEnumerable<Byte[]> SplitByteArray(IEnumerable<Byte> source, byte marker) {
  if (null == source)
    throw new ArgumentNullException("source");

  List<byte> current = new List<byte>();

  foreach (byte b in source) {
    if (b == marker) {
      if (current.Count > 0)
        yield return current.ToArray();

      current.Clear();
    }

    current.Add(b);
  }

  if (current.Count > 0)
    yield return current.ToArray();
}

and use it:

  String source = "08 FF FF 47 FF FF FF 47 FF FF 47 FF 47 FF FF FF FF 47 FF FF";

  // the data
  Byte[] data = source
    .Split(' ')
    .Select(x => Convert.ToByte(x, 16))
    .ToArray();

  // splitted
  Byte[][] result = SplitByteArray(data, 0x47).ToArray();

  // data splitted has been represented for testing
  String report = String.Join(Environment.NewLine, 
    result.Select(line => String.Join(" ", line.Select(x => x.ToString("X2")))));

  // 08 FF FF
  // 47 FF FF FF
  // 47 FF FF
  // 47 FF
  // 47 FF FF FF FF
  // 47 FF FF
  Console.Write(report);
Sign up to request clarification or add additional context in comments.

Comments

2

A possible solution:

byte[] source = // ...
string packet = String.Join(" ", source.Select(b => b.ToString("X2")));

// chunks is of type IEnumerable<IEnumerable<byte>>
var chunks = Regex.Split(packet, @"(?=47)")
             .Select(c =>
                 c.Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                 .Select(x => Convert.ToByte(x, 16)));

Comments

1

Maybe a little too hacky for you, but should work just fine:

string ins = "08 FF FF 47 FF FF FF 47 FF FF 47 FF 47 FF FF FF FF 47 FF FF ";
string[] splits = ins.Split(new string[] { "47" }, StringSplitOptions.None);
for (int i = 0; i < splits.Length; i++) {
     splits[i] = "47 " + splits[i];
}

Edit: similar to the already existing answer I guess.

Comments

0

There's a couple of ways to do this, the easiest approach is to just use .Split() and replace the value that is being split on.

string[] values = packet.Split("47");
for(int i = 0; i < values.Length; i++)
{
    Console.WriteLine("[{0}] 47 {1}", i, values[i]);
    // C# 6+ way: Console.WriteLine($"[{i}] 47 {values[i]}");
}

Of course, you can always use regular expressions, but my Regex skills are pretty limited and I don't think I could personally construct a valid regex for this.

2 Comments

This would work, string[] mpegPackets = Regex.Split(data, "(?=47)"); I guess you are right I need to convert the hex values to string in order to split.
Isn't the question about an Array of bytes?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.