2015-11-16 6 views
1

Есть ли способ в C# преобразовать простой массив байтов в объект?Преобразование байтового массива в объект

дал например этот класс:

class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 
} 

Я хочу, чтобы в основном быть в состоянии сделать что-то вроде этого:

var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; 
var obj = (Data)bytes; 
+0

Что вы хотите достичь? Должен быть какой-то логин в отношении между вашими байтами и экземпляром, который вы хотите создать. –

+2

Технически вы можете реализовать оператор * *, т. Е. Публичный статический явный оператор Data (Byte [] source) {...} 'но * сериализация * - гораздо лучшее решение. –

+1

Получить представление - [См. Здесь] (http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html) – pedram

ответ

5

Вы можете попробовать сортировочных:

Объявить макет вашего класса как Sequential (и обратите внимание, что вам нужно будет использовать Pack = 1):

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 
} 

Маршал байты в новый экземпляр класса данных:

var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; 
GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
gcHandle.Free(); 

// Now data should contain the correct values. 

Console.WriteLine(data._int1); // Prints 1 
Console.WriteLine(data._int2); // Prints 2 
Console.WriteLine(data._short1); // Prints 3 
Console.WriteLine(data._long1); // Prints 4 

Для удобства вы можете написать статический метод данных для выполнения преобразования:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 

    public static Data FromBytes(byte[] bytes) 
    { 
     GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
     gcHandle.Free(); 
     return data; 
    } 
} 

... 

var data = Data.FromBytes(new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0}); 

Если вы действительно хотели, чтобы вы могли написать явный оператор для преобразования из массива байтов, чтобы получить синтаксис в вашем OP. Я бы предложил просто использовать Data.FromBytes(), который будет намного понятнее ИМО.

Тем не менее, только для полноты:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 

    public static explicit operator Data(byte[] bytes) 
    { 
     GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
     gcHandle.Free(); 
     return data; 
    } 
} 

... 

var data = (Data)new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0}; 
+0

@OguzOzgul Полностью не соответствует действительности. [Вы можете маршалировать классы или структуры] (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute%28v=vs.71%29.aspx). –

+0

Извините, ошибочно ошибочно. изменено на upvote. –

+0

Спасибо, я думаю, что, учитывая то, что я пытаюсь сделать, это лучший ответ. – Mark

1

BitConverter.ToInt32/Int16/Int64 Использование методов. Вы только должны указать начальный индекс, как:

Data data = new Data(); 
data._int1 = BitConverter.ToInt32(bytes, 0); 
data._int2 = BitConverter.ToInt32(bytes, 4); 
data._short1 = BitConverter.ToInt16(bytes, 8); 
data._long1 = BitConverter.ToInt64(bytes,10); 

Только помните:

BitConverter.ToInt32

Порядок байтов в массиве должны отражать порядка байтов архитектуры компьютерной системы;

0

Нет ничего, что сделало бы преобразование за один раз.

Но вы можете построить на вершине BitConverter:

var d = new Data(); 
var sI32 = sizeof(Int32); 
d._int1 = BitConverter.ToInt32(bytes, 0); 
d._int2 = BitConverter.ToInt32(bytes, sI32); 
d._short1 = BitConverter.ToInt16(bytes, 2*sI32); 
… 
Смежные вопросы