net imagen convertir convert bytes arreglo array c#

imagen - Cómo convertir un objeto a una matriz de bytes en C#



picturebox to byte array c# (11)

Tengo una colección de objetos que necesito escribir en un archivo binario.

Necesito que los bytes en el archivo sean compactos, así que no puedo usar BinaryFormatter . BinaryFormatter todo tipo de información para las necesidades de deserialización.

Si lo intento

byte[] myBytes = (byte[]) myObject

Obtengo una excepción de tiempo de ejecución.

Necesito que esto sea rápido, así que preferiría no estar copiando matrices de bytes a mi alrededor. Simplemente me gustaría que el byte[] myBytes = (byte[]) myObject reparto byte[] myBytes = (byte[]) myObject funcione!

OK para ser claro, no puedo tener ningún metadato en el archivo de salida. Solo los bytes del objeto. Empaquetado objeto a objeto. Según las respuestas recibidas, parece que escribiré un código Buffer.BlockCopy bajo nivel. Tal vez utilizando código inseguro.


Bueno, una conversión de myObject a byte[] nunca funcionará a menos que tenga una conversión explícita o si myObject es un byte[] . Necesitas un marco de serialización de algún tipo. Hay muchos por ahí, incluyendo Protocol Buffers, que es cercano y querido para mí. Es bastante "delgado y mezquino" en términos tanto de espacio como de tiempo.

Encontrará que casi todos los marcos de serialización tienen restricciones significativas sobre lo que puede serializar, sin embargo, los búferes de protocolo más que algunos, debido a que son multiplataforma.

Si puedes dar más requisitos, podemos ayudarte más, pero nunca será tan simple como lanzar ...

EDIT: Sólo para responder a esto:

Necesito que mi archivo binario contenga los bytes del objeto. Sólo los bytes, sin metadatos en absoluto. Empaquetado objeto a objeto. Así que estaré implementando una serialización personalizada.

Tenga en cuenta que los bytes en sus objetos son a menudo referencias ... así que tendrá que averiguar qué hacer con ellos.

Sospecho que encontrará que diseñar e implementar su propio marco de serialización personalizado es más difícil de lo que imagina.

Personalmente, recomendaría que si solo necesita hacer esto para algunos tipos específicos, no se moleste en intentar crear un marco de serialización general. Simplemente implemente un método de instancia y un método estático en todos los tipos que necesita:

public void WriteTo(Stream stream) public static WhateverType ReadFrom(Stream stream)

Una cosa a tener en cuenta: todo se vuelve más complicado si se trata de una herencia. Sin herencia, si sabe con qué tipo de letra comienza, no necesita incluir ninguna información de tipo. Por supuesto, también existe la cuestión del control de versiones: ¿debe preocuparse por la compatibilidad con versiones anteriores y posteriores con diferentes versiones de sus tipos?


Convertir un objeto a la matriz de bytes:

// Convert an object to a byte array public static byte[] ObjectToByteArray(Object obj) { BinaryFormatter bf = new BinaryFormatter(); using (var ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } }

Solo necesita copiar esta función a su código y enviarle el objeto que necesita convertir a matriz de bytes. Si necesita volver a convertir la matriz de bytes en objeto, puede usar la siguiente función:

// Convert a byte array to an Object public static Object ByteArrayToObject(byte[] arrBytes) { using (var memStream = new MemoryStream()) { var binForm = new BinaryFormatter(); memStream.Write(arrBytes, 0, arrBytes.Length); memStream.Seek(0, SeekOrigin.Begin); var obj = binForm.Deserialize(memStream); return obj; } }

Puedes usar estas funciones con clases personalizadas. Solo necesita agregar el atributo [Serializable] en su clase para habilitar la serialización


Creo que lo que estás tratando de hacer es imposible.

La basura que crea BinaryFormatter es necesaria para recuperar el objeto del archivo después de que su programa se haya detenido.
Sin embargo, es posible obtener los datos del objeto, solo necesita saber su tamaño exacto (más difícil de lo que parece):

public static unsafe byte[] Binarize(object obj, int size) { var r = new byte[size]; var rf = __makeref(obj); var a = **(IntPtr**)(&rf); Marshal.Copy(a, r, 0, size); return res; }

Esto se puede recuperar a través de:

public unsafe static dynamic ToObject(byte[] bytes) { var rf = __makeref(bytes); **(int**)(&rf) += 8; return GCHandle.Alloc(bytes).Target; }

La razón por la que los métodos anteriores no funcionan para la serialización es que los primeros cuatro bytes en los datos devueltos corresponden a un RuntimeTypeHandle . El RuntimeTypeHandle describe el diseño / tipo del objeto pero su valor cambia cada vez que se ejecuta el programa.

EDIT: eso es estúpido, no haga eso -> Si ya conoce el tipo de objeto que desea deserializar, puede cambiar esos bytes por BitConvertes.GetBytes((int)typeof(yourtype).TypeHandle.Value) en El tiempo de la deserialización.


Eche un vistazo a la Serialization , una técnica para "convertir" un objeto completo en un flujo de bytes. Puede enviarlo a la red o escribirlo en un archivo y luego restaurarlo en un objeto más tarde.


Encontré otra forma de convertir objeto en byte []. Hier es mi solución:

IEnumerable en = (IEnumerable) myObject; byte[] myBytes = en.OfType<byte>().ToArray();

Saludos


Esto funcionó para mí:

byte[] bfoo = (byte[])foo;

foo es un Objeto que estoy 100% seguro de que es una matriz de bytes.


Para acceder directamente a la memoria de un objeto (para hacer un "volcado de memoria"), deberá ingresar al código no seguro.

Si desea obtener algo más compacto que BinaryWriter o un volcado de memoria sin formato, debe escribir un código de serialización personalizado que extraiga la información crítica del objeto y la empaque de una manera óptima.

edita PS Es muy fácil envolver el enfoque de BinaryWriter en un DeflateStream para comprimir los datos, que por lo general reducen a la mitad el tamaño de los datos.


Realmente estás hablando de serialización, que puede tomar muchas formas. Como usted quiere pequeños y binarios, los búferes de protocolo pueden ser una opción viable, ya que también brindan tolerancia y portabilidad de la versión. A diferencia de BinaryFormatter , el formato de búfer de protocolo no incluye todos los metadatos de tipo; Sólo marcadores muy concisos para identificar datos.

En .NET hay algunas implementaciones; en particular

Argumentaría humildemente que protobuf-net (que escribí) permite más uso idiomático de .NET con las clases típicas de C # (los búferes de protocolo "regulares" tienden a exigir la generación de código); por ejemplo:

[ProtoContract] public class Person { [ProtoMember(1)] public int Id {get;set;} [ProtoMember(2)] public string Name {get;set;} } .... Person person = new Person { Id = 123, Name = "abc" }; Serializer.Serialize(destStream, person); ... Person anotherPerson = Serializer.Deserialize<Person>(sourceStream);


Si desea que los datos serializados sean realmente compactos, puede escribir los métodos de serialización usted mismo. De esa manera tendrás un mínimo de gastos generales.

Ejemplo:

public class MyClass { public int Id { get; set; } public string Name { get; set; } public byte[] Serialize() { using (MemoryStream m = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(m)) { writer.Write(Id); writer.Write(Name); } return m.ToArray(); } } public static MyClass Desserialize(byte[] data) { MyClass result = new MyClass(); using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { result.Id = reader.ReadInt32(); result.Name = reader.ReadString(); } } return result; } }


Si solo tenía texto o algo similar para almacenar, podría hacer algo como: byte [] byteArray = Encoding.ASCII.GetBytes (myObject.text);

De lo contrario, tendrás que serializar de una manera más complicada.


Tomé la respuesta de Crystalonics y los convertí en métodos de extensión. Espero que alguien más los encuentre útiles:

public static byte[] SerializeToByteArray(this object obj) { if (obj == null) { return null; } var bf = new BinaryFormatter(); using (var ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } } public static T Deserialize<T>(this byte[] byteArray) where T : class { if (byteArray == null) { return null; } using (var memStream = new MemoryStream()) { var binForm = new BinaryFormatter(); memStream.Write(byteArray, 0, byteArray.Length); memStream.Seek(0, SeekOrigin.Begin); var obj = (T)binForm.Deserialize(memStream); return obj; } }