我正在尝试在解串通过ProtoBuf.Net存储的对象之前,有一种方法可以解决我在Stream中读取MemoryStream的问题。
我无法使用带有LengthPrefix功能的Protobuf.Net,因为我回来并在写入新记录时调整文件中的记录,以便可以向后或向前遍历文件。序列化类不需要更改,因为我将3长度与实际类别分开。
这是我目前用于阅读条目的代码:
Private Function ReadEntry(ByVal br As BinaryReader) As PacketErrorLogEntry
Dim activeRecord As PacketErrorLogEntry
Dim OffsetPrevious As UInt32 = br.ReadUInt32()
Dim RecordLength As UInt32 = br.ReadUInt32
Dim OffsetNext As UInt32 = br.ReadUInt32
Using ms As New MemoryStream
Dim readLength As UInt32
Dim bytesRead As UInt32
Dim writeBuffer As Byte() = CType(Array.CreateInstance(GetType(Byte), _
4096), Byte())
Dim bytesToRead As UInt32 = CType(writeBuffer.Length, UInt32)
If bytesToRead > RecordLength Then
bytesToRead = RecordLength
End If
bytesRead = 0
While readLength < RecordLength
bytesRead = CType(br.BaseStream.Read(writeBuffer, 0, _
CType(bytesToRead, Integer)), UInt32)
ms.Write(writeBuffer, 0, CType(bytesRead, Integer))
readLength += bytesRead
End While
ms.Flush()
ms.Position = 0
activeRecord = Serializer.Deserialize(Of PacketErrorLogEntry)(ms)
activeRecord.PreviousRecordLocation = OffsetPrevious
activeRecord.NextRecordLocation = OffsetNext
End Using
'activeRecord = Serializer.Deserialize(Of PacketErrorLogEntry)(br.BaseStream, RecordLength)
'activeRecord.PreviousRecordLocation = OffsetPrevious
'activeRecord.NextRecordLocation = OffsetNext
Return activeRecord
End Function
我希望我能够实现的是通过将Length to Read传递给Deserialize函数,然后我就可以取消整个MemoryStream块并让我的对象恢复。
我使用BinaryReader / Writer作为长度/偏移量,以便我可以稍后返回,只是用更新的值覆盖这些位置。
答案 0 :(得分:1)
如果您使用的是v2,那么TypeModel
API(实际上是主要API; Serializer.Deserialize<T>
API只调用RuntimeTypeModel.Default.Deserialize
)就可以使用此功能。有些重载接受要使用的字节数。一旦这样的方法(在TypeModel
实例上,很可能是RuntimeTypeModel.Default
)是:
/// <summary>
/// Applies a protocol-buffer stream to an existing instance (which may be null).
/// </summary>
/// <param name="type">The type (including inheritance) to consider.</param>
/// <param name="value">The existing instance to be modified (can be null).</param>
/// <param name="source">The binary stream to apply to the instance (cannot be null).</param>
/// <param name="length">The number of bytes to consume.</param>
/// <returns>The updated instance; this may be different to the instance argument if
/// either the original instance was null, or the stream defines a known sub-type of the
/// original instance.</returns>
public object Deserialize(Stream source, object value, Type type, int length);
我还应该注意,“with length prefix”API也允许使用不同的前缀样式,固定长度(big-endian或little-endian)int32可用。但是你当前的方法也应该可以正常工作。
如果您使用v1,则可能必须制作长度受限的流....或仅borrow the one that v1 uses internally(请注意,v2不使用此方法 - 它会跟踪单个上的剩余活动字节流加缓冲区。)