Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the fastest (possibly unsafe) way to read a byte[]?

I'm working on a server project in C#, and after a TCP message is received, it is parsed, and stored in a byte[] of exact size. (Not a buffer of fixed length, but a byte[] of an absolute length in which all data is stored.)

Now for reading this byte[] I'll be creating some wrapper functions (also for compatibility), these are the signatures of all functions I need:

public byte ReadByte();
public sbyte ReadSByte();
public short ReadShort();
public ushort ReadUShort();
public int ReadInt();
public uint ReadUInt();
public float ReadFloat();
public double ReadDouble();
public string ReadChars(int length);
public string ReadString();

The string is a \0 terminated string, and is probably encoded in ASCII or UTF-8, but I cannot tell that for sure, since I'm not writing the client.

The data exists of:

byte[] _data;
int _offset;

Now I can write all those functions manually, like this:

public byte ReadByte()
{
    return _data[_offset++];
}

public sbyte ReadSByte()
{
    byte r = _data[_offset++];
    if (r >= 128) return (sbyte)(r - 256);
    else return (sbyte)r;
}

public short ReadShort()
{
    byte b1 = _data[_offset++];
    byte b2 = _data[_offset++];
    if (b1 >= 128) return (short)(b1 * 256 + b2 - 65536);
    else return (short)(b1 * 256 + b2);
}

public short ReadUShort()
{
    byte b1 = _data[_offset++];
    return (short)(b1 * 256 + _data[_offset++]);
}

But I wonder if there's a faster way, not excluding the use of unsafe code, since this seems to cost too much time for simple processing.

like image 203
Aidiakapi Avatar asked Mar 04 '11 15:03

Aidiakapi


2 Answers

Check out the BitConverter class, in the System namespace. It contains methods for turning parts of byte[]s into other primitive types. I've used it in similar situations and have found it suitably quick.

As for decoding strings from byte[]s, use the classes that derive from the Encoding class, in the System.Text namespace, specifically the GetString(byte[]) method (and its overloads).

like image 132
Erik Forbes Avatar answered Oct 14 '22 02:10

Erik Forbes


One way is to map the contents of the array to a struct (providing your structure is indeed static):

http://geekswithblogs.net/taylorrich/archive/2006/08/21/88665.aspx

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct Message
{
    public int id;
    [MarshalAs (UnmanagedType.ByValTStr, SizeConst=50)] 
    public string text;
}

void OnPacket(byte[] packet)
{
    GCHandle pinnedPacket = GCHandle.Alloc(packet, GCHandleType.Pinned);
    Message msg = (Message)Marshal.PtrToStructure(
        pinnedPacket.AddrOfPinnedObject(),
        typeof(Message));        
    pinnedPacket.Free();
}
like image 22
RQDQ Avatar answered Oct 14 '22 02:10

RQDQ