Какой самый быстрый (возможно, небезопасный) способ чтения байта []? - PullRequest
7 голосов
/ 04 марта 2011

Я работаю над серверным проектом на C #, и после получения TCP-сообщения оно анализируется и сохраняется в байте [] точного размера. (Не буфер фиксированной длины, а байт [] абсолютной длины, в котором хранятся все данные.)

Теперь для чтения этого байта [] я буду создавать некоторые функции-оболочки (также для совместимости), это сигнатуры всех необходимых мне функций:

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();

Строка является завершенной \ 0 строкой и, вероятно, закодирована в ASCII или UTF-8, но я не могу сказать это точно, так как я не пишу клиент.

Данные существуют:

byte[] _data;
int _offset;

Теперь я могу написать все эти функции вручную, например:

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

Но мне интересно, есть ли более быстрый способ, не исключающий использования небезопасного кода, поскольку это кажется слишком дорогим для простой обработки.

Ответы [ 3 ]

6 голосов
/ 04 марта 2011

Проверьте класс BitConverter в пространстве имен системы. Он содержит методы для преобразования частей byte [] в другие примитивные типы. Я использовал его в подобных ситуациях и нашел это достаточно быстро.

Что касается декодирования строк из байтов [], используйте классы, производные от класса Encoding , в пространстве имен System.Text, в частности, GetString (byte []) метод (и его перегрузки).

3 голосов
/ 04 марта 2011

Один из способов - сопоставить содержимое массива со структурой (при условии, что ваша структура действительно статична):

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();
}
1 голос
/ 04 марта 2011

Вы можете использовать BinaryReader .

BinaryReader - это потоковый декоратор, поэтому вам нужно будет обернуть byte[] в MemoryStream или подключить Reader непосредственно к сетевому потоку.

И тогда у вас есть

int ReadInt32()
char[] ReadChars(int count)

и т. Д.


Редактировать: Очевидно, вы хотите «более быстрое выполнение».

Это означает, что вы ищете оптимизацию в преобразовании (ях) из byte[] после получения этих байтов.через (сетевой) ввод / вывод.

Другими словами, вы пытаетесь оптимизировать ту часть, которая занимает (приблизительно) 0,1% времени.Совершенно бесполезно.

...