3

I'm trying to translate a function from ActionScript 3 into C# .NET.

What I have trouble is how to properly use ByteArrays in C#. In As3 there is a specific Class for it that already has most of the functionality i need, but in C# nothing of that sort seems to exist and I can't wrap my head around it.

This is the As3 function:

private function createBlock(type:uint, tag:uint,data:ByteArray):ByteArray
        {
            var ba:ByteArray = new ByteArray();
            ba.endian = Endian.LITTLE_ENDIAN;
            ba.writeUnsignedInt(data.length+16);
            ba.writeUnsignedInt(0x00);
            ba.writeUnsignedInt(type);
            ba.writeUnsignedInt(tag);
            data.position = 0;
            ba.writeBytes(data);
            ba.position = 0;

            return ba;  
        }

But from what I gather, in C# I have to use a normal Array with the byte type, like this

byte[] ba = new byte[length];

Now, I looked into the Encoding Class, the BinaryWriter and BinaryFormatter class and researched if somebody made a Class for ByteArrays, but with no luck.

Can somebody nudge me in the right direction please?

  • What is the function trying to do? there may be better alternatives – Sayse Sep 03 '14 at 07:42
  • Take a look at the Stream class. http://msdn.microsoft.com/en-us/library/system.io.stream(v=vs.110).aspx – ne1410s Sep 03 '14 at 07:43
  • @Sayse It's adding a header to the byte array that defines some meta information. –  Sep 03 '14 at 07:44
  • @DodgerThud - I meant what are you attempting to do with that byte array, you may find there are other classes that can be used instead (i.e the stream class already shown) – Sayse Sep 03 '14 at 07:44
  • @Sayse The ByteArray will be later sent through a socket to a device. –  Sep 03 '14 at 07:47
  • You may wish to take a look around for alternatives also, such as [Socket class](http://msdn.microsoft.com/en-us/library/system.net.sockets.socket(v=vs.110).aspx), best of luck anyway. – Sayse Sep 03 '14 at 07:51

2 Answers2

4

You should be able to do this using a combination of MemoryStream and BinaryWriter:

public static byte[] CreateBlock(uint type, uint tag, byte[] data)
{
    using (var memory = new MemoryStream())
    {
        // We want 'BinaryWriter' to leave 'memory' open, so we need to specify false for the third
        // constructor parameter. That means we need to also specify the second parameter, the encoding.
        // The default encoding is UTF8, so we specify that here.

        var defaultEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier:false, throwOnInvalidBytes:true);

        using (var writer = new BinaryWriter(memory, defaultEncoding, leaveOpen:true))
        {
            // There is no Endian - things are always little-endian.

            writer.Write((uint)data.Length+16);
            writer.Write((uint)0x00);
            writer.Write(type);
            writer.Write(data);
        }

        // Note that we must close or flush 'writer' before accessing 'memory', otherwise the bytes written
        // to it may not have been transferred to 'memory'.

        return memory.ToArray();
    }
}

However, note that BinaryWriter always uses little-endian format. If you need to control this, you can use Jon Skeet's EndianBinaryWriter instead.

As an alternative to this approach, you could pass streams around instead of byte arrays (probably using a MemoryStream for implementation), but then you will need to be careful about lifetime management, i.e. who will close/dispose the stream when it's done with? (You might be able to get away with not bothering to close/dispose a memory stream since it uses no unmanaged resources, but that's not entirely satisfactory IMO.)

Community
  • 1
  • 1
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 1
    Thanks, your previous answer was already perfect. But thanks for adding an alternative approach. I got it working just the way I needed. –  Sep 03 '14 at 10:41
1

You want to have a byte stream and then extract the array from it:

using(MemoryStream memory = new MemoryStream())
using(BinaryWriter writer = new BinaryWriter(memory))
{
    // write  into stream
    writer.Write((byte)0); // a byte
    writer.Write(0f);      // a float
    writer.Write("hello"); // a string

    return memory.ToArray(); // returns the underlying array
}
pid
  • 11,472
  • 6
  • 34
  • 63
  • This also works but Matthew was a tad faster and provided more info. But thank you for you help. –  Sep 03 '14 at 10:41