当.NET BinaryFormatter用于序列化对象图时,是否应用了任何类型的压缩?
我在上下文中询问是否应该担心具有许多重复字符串和整数的对象图.
编辑 - 保持,如果在.NET中实例化字符串,则无需担心重复的字符串,对吧?
我写了一个自定义类MyClass并用<Serializable()>属性标记它.我在我的硬盘驱动器上有一组二进制文件,我使用BinaryFormatter来自实例的序列化MyClass.
我最近MyClass稍微改变了结构(添加了一些属性,删除了一些属性,改变了一些方法等).
当我尝试使用下面的代码将现有对象反序列化为此更改的类时会发生什么?我已经尝试了它并没有抛出错误或任何东西 - 但是当类改变时它肯定无法正确反序列化?有没有办法可以从序列化文件中获取一些有用的信息,即使我已经更新了这个类?
谢谢.
这是我用来进行序列化的代码:
Public Sub serializeObject(ByVal obj As Object, ByVal outFilename As String)
Dim fStream As FileStream
Try
fStream = New FileStream(outFilename, FileMode.Create)
Dim bfmtr As New BinaryFormatter
bfmtr.Serialize(fStream, obj)
fStream.Close()
Catch ex As Exception
MsgBox("Failed to serialize: " & ex.Message)
Throw
End Try
End Sub
Run Code Online (Sandbox Code Playgroud)
并且我正在使用反序列化:
myObj = CType(deserializeObject("C:\myobject.bin"), MyClass))
Run Code Online (Sandbox Code Playgroud)
在哪里deserializeObject:
Public Function deserializeObject(ByVal srcFilename As String) As Object
If File.Exists(srcFilename) Then …Run Code Online (Sandbox Code Playgroud) vb.net serialization visual-studio-2010 binaryformatter deserialization
我试图使用以下方法在.NET中序列化对象图:
public static byte[] Serialize(object data)
{
var binary = new BinaryFormatter();
using (var ms = new MemoryStream()) {
binary.Serialize(ms, data);
return ms.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我遇到以下错误:
FormatException: Input string was not in a correct format.
Stack Trace:
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ToInt32(Object value, IFormatProvider provider)
at System.Runtime.Serialization.Formatters.Binary.__BinaryWriter.WriteValue(InternalPrimitiveTypeE code, Object value)
at System.Runtime.Serialization.Formatters.Binary.__BinaryWriter.WriteMember(NameInfo memberNameInfo, NameInfo typeNameInfo, Object value)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteKnownValueClass(NameInfo memberNameInfo, NameInfo typeNameInfo, …Run Code Online (Sandbox Code Playgroud) 在 .NET5 之前,我们通过以下代码序列化/反序列化字节/对象:
private static byte[] StructToBytes<T>(T t)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, t);
return ms.ToArray();
}
}
private static T BytesToStruct<T>(byte[] bytes)
{
using (var memStream = new MemoryStream())
{
var binForm = new BinaryFormatter();
memStream.Write(bytes, 0, bytes.Length);
memStream.Seek(0, SeekOrigin.Begin);
var obj = binForm.Deserialize(memStream);
return (T)obj;
}
}
Run Code Online (Sandbox Code Playgroud)
但出于安全原因,BinaryFormatter 将被删除:
https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/binaryformatter-security-guide
那么有没有一些简单但高性能的方法来代替 BinaryFormatter 呢?
微软警告不要使用BinaryFormatter(他们写道没有办法保证反序列化的安全)。
应用程序应尽快停止使用 BinaryFormatter,即使它们认为正在处理的数据是值得信赖的。
我不想使用基于XML或Json的解决方案(这是他们所指的)。我担心文件大小和保留对象图。
如果我要编写自己的方法来遍历我的对象图并将对象转换为二进制,那么可以安全地制作它,还是从二进制转换为特殊内容使其本质上比文本更危险?
使用BinaryFormatter进行序列化/反序列化,生成的序列化文件大小约为80MB.反序列化需要几分钟.我怎么能改进这个?这是反序列化代码:
public static Universe DeserializeFromFile(string filepath)
{
Universe universe = null;
FileStream fs = new FileStream(filepath, FileMode.Open);
BinaryFormatter bf = new BinaryFormatter();
try
{
universe = (Universe)bf.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
return universe;
}
Run Code Online (Sandbox Code Playgroud)
也许在反序列化之前读取所有内存或使用其他一些序列化技术?
我必须使用一个旧的应用程序,它使用binaryFormatter将应用程序数据序列化到文件流中(例如在一个名为"data.oldformat"的文件中),而没有任何优化主类已经标记了属性
<serializable()>public MainClass
.......
end class
Run Code Online (Sandbox Code Playgroud)
和序列化代码
dim b as new binaryformatter
b.serialize(mystream,mymainclass)
Run Code Online (Sandbox Code Playgroud)
为了优化序列化/反序列化过程,我简单地使类实现了ISerializable接口并编写了一些优化的序列化例程
<serializable()>public MainClass
implements ISerializable
.......
end class
Run Code Online (Sandbox Code Playgroud)
优化工作非常好但我必须找到一种方法来恢复旧文件中的数据以实现向后兼容.
我怎样才能做到这一点??
皮耶路易吉
我正在测试BinaryFormatter,看看它对我有用,我有一个简单的问题:
当它与字符串HELLO一起使用时,我将MemoryStream转换为数组,它给出了29个维度,其中五个是维度末尾的实际数据:
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
byte[] bytes;
string originalData = "HELLO";
bf.Serialize(ms, originalData);
ms.Seek(0, 0);
bytes = ms.ToArray();
Run Code Online (Sandbox Code Playgroud)
回报
- bytes {Dimensions:[29]} byte[]
[0] 0 byte
[1] 1 byte
[2] 0 byte
[3] 0 byte
[4] 0 byte
[5] 255 byte
[6] 255 byte
[7] 255 byte
[8] 255 byte
[9] 1 byte
[10] 0 byte
[11] 0 byte
[12] 0 byte
[13] 0 byte
[14] 0 byte
[15] 0 byte
[16] 0 …Run Code Online (Sandbox Code Playgroud) 我正在寻找有关.net应用程序序列化的建议.该应用程序是桌面/胖客户端应用程序,序列化表示持久文档格式.序列化器的要求是
目前我们使用BinaryFormatter来处理上述所有问题,但是尺寸/性能和版本容差是个问题.我们使用[OnDeserialized/ing]属性来提供兼容性,但它不允许大型重构(比如命名空间更改)而不需要复杂使用代理等等.
理想的解决方案是直接替换BinaryFormatter,它可以与我们现有的[NonSerialized]注释等一起使用,但性能更好,并且生成的格式更小,更易于维护.
我已经查看了不同的protobuf实现,尽管现在似乎可以序列化一般对象图/枚举/结构,但是使用大量框架集类型等序列化复杂图形似乎并不容易.而且,即使我们可以使用字段而不是属性我理解它仍然意味着必须向所有类添加无参数构造函数和protobuf注释(域约为1000个类).
所以问题:
假设我有这个课程:
[Serializable]
public class SomeClass
{
public SomeClass() {//init}
public string SomeString {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
该类在应用程序关闭时获取Serialized,并在下次运行时进行反序列化.
然后,我构建它并发布了应用程序,现在该类已更改:
[Serializable]
public class SomeClass
{
public SomeClass() {//init}
public string SomeString {get;set;}
public int SomeInt {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在反序列化时将属性设置为默认值,以防在旧的序列化对象中找不到它?
我想到的一种方法是保留类的旧版本,然后检查序列化的版本然后循环旧对象的属性并在新对象中设置它们,但这对我来说是没有意义的,任何其他有意义的解决方案?
binaryformatter ×10
c# ×7
.net ×4
.net-5 ×1
compression ×1
memorystream ×1
performance ×1
vb.net ×1