我之前看过这类问题,但不确定问题的根本原因是什么或如何解决。
我正在修改现有的类,以便能够将数据加载到flash中的成员变量中。现在,该类通过load函数从文件加载数据。此函数已重载以接收字节数组。
从闪存读回的数据被放入该字节数组中
抛出的错误是(发生在... = formatter.Deserialize(stream)
行):
输入流不是有效的二进制格式。起始内容(以字节为单位)为:93-E3-E6-3F-C3-F5-E4-41-00-C0-8D-C3-14-EE-4A-C3-00 ...
这里有趣的是内容正是传递给流的字节数组的内容。换句话说,这是来自闪存的数据,这正是我想要序列化的。我不确定为什么会抛出错误。
或者更好的问题是什么是BinaryFormatter
的有效二进制格式?它需要一定的尺寸吗?是否需要特定的最终价值?某些值无效吗?字节数组输入的当前大小为24字节。
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Media.Imaging;
using System.IO;
using Galileo.Data;
using System.Xml.Serialization;
using System.Reflection;
using System.Runtime.InteropServices;
using UComm;
using System.Runtime.Serialization.Formatters.Binary;
using ULog;
public void Load(byte[] spCalfromPrimary)
{
try
{
Type settingsType = this.GetType();
object tmp = Activator.CreateInstance(settingsType);
Stream stream = new MemoryStream();
stream.Write(spCalfromPrimary, 0, spCalfromPrimary.Length);
stream.Position = 0;
BinaryFormatter formatter = new BinaryFormatter();
//tmp = formatter.Deserialize(stream);
formatter.Deserialize(stream); //**<--- throws error here**
// Use reflection to copy all public properties from the temporary object into this one.
PropertyInfo[] properties = settingsType.GetProperties();
foreach (PropertyInfo property in properties)
{
object value = property.GetValue(tmp, null);
if (value == null)
{
throw new FileFormatException("Null value encountered in settings file");
}
else
{
property.SetValue(this, value, null);
}
}
}
catch (Exception ex)
{
_logger.DebugException("Failed to load spatial cal value from FW", ex);
Console.WriteLine(ex.Message);
}
}
// <summary>
/// Loads the setting from file
/// </summary>
public void Load()
{
Type settingsType = this.GetType();
XmlSerializer xser = new XmlSerializer(settingsType);
object tmp = Activator.CreateInstance(settingsType);
using (StreamReader reader = new StreamReader(_filename)) { tmp = xser.Deserialize(reader); }
// Use reflection to copy all public properties from the temporary object into this one.
PropertyInfo[] properties = settingsType.GetProperties();
foreach (PropertyInfo property in properties)
{
object value = property.GetValue(tmp, null);
if (value == null)
{
throw new FileFormatException("Null value encountered in settings file");
}
else
{
property.SetValue(this, value, null);
}
}
}
请注意,我还尝试了将Convert字节数组转换为对象函数(我在stackoverflow上找到)。当我使用这个函数时,.Deserialize(memStream)
仍然会抛出异常。
// Convert a byte array to an Object
private Object ByteArrayToObject(byte[] arrBytes)
{
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(arrBytes, 0, arrBytes.Length);
memStream.Seek(0, SeekOrigin.Begin);
Object obj = (Object) binForm.Deserialize(memStream);
return obj;
}
显然我遗漏了一些重要信息。
序列化发生在与反序列化不同的应用程序中。序列化使用位转换器获取数据,转换为字节数组并将其上载到闪存。让我解释。正在序列化/反序列化的数据&amp;存储在闪存中的是校准数据。通过生产,在工厂使用Application1进行校准。这使用位转换器将每个字段放入流中,然后序列化流。
CFlatInterface.FloatToStream(bData, ref i, rtsMappingData.ScaleTrackingDMD);
CFlatInterface.FloatToStream(bData, ref i, rtsMappingData.RotationAngle);
CFlatInterface.FloatToStream(bData, ref i, rtsMappingData.CenterOfRotation.dx);
其中FloatToStream函数定义为:
public static void FloatToStream(byte[] buf, ref int index, float val)
{
Buffer.BlockCopy(BitConverter.GetBytes(val), 0, buf, index, sizeof(float));
index += sizeof(float);
}
因此,构成校准的每个字段都以这种方式放入流中。数据被放入流中,并构造一个字节数组并发送到闪存。
另一方面,一旦产品出厂并使用,Application2(用户应用程序)就会有一个具有所有校准字段的校准对象。这将读取闪存,并获取Application1写入的数据。 Application2正在尝试使用BinaryFormatter和上面的代码对校准数据进行反序列化。我得出的结论是不可能的(谢谢Rotem)。正确的做法是对序列化/反序列化使用相同的格式化程序 - 我将以这种方式实现它并指出是否有所作为。
答案 0 :(得分:4)
更新后,显而易见的问题是您使用不同的格式化程序进行序列化和反序列化。
BinaryFormatter
序列化的不仅仅是字段数据。它还序列化了类型信息和元数据,因此它知道如何反序列化对象,因此它不仅仅需要原始数据字节作为输入。
也可以在序列化端使用BinaryFormatter
,或者在接收端使用手动反序列化技术。