二进制序列化的优化问题

qjf9013 2010-01-04 02:34:57
条件及原因如下:
1.只能用binaryformatter
2.在数据量超大的时候,序列化会出现错误。无法解决。
问题:
1.如何优化二进制序列化
2.怎么自己定制binaryformatter
谢谢
...全文
222 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
yamakasi4050 2010-01-04
  • 打赏
  • 举报
回复
忘了枚举的定义
public enum SerializeDirection{LOAD,SAVE};
吃饭去了
调用
NetworkStream ns = new NetworkStream(inSock);
BinSerializer bs = new BinSerializer(ns);
序列化并网络发送
bs.Save(obj);
反序列化并网络接收
... obj = (...)bs.Load();
就可以了
因为项目是网络通讯,你如果不是改改就行了 代码几个类都是完整的
QQ22943213
22943213
qjf9013 2010-01-04
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 yamakasi4050 的回复:]
[/Quote]

谢谢你啊 。有没有QQ 呵呵 ^ ^
yamakasi4050 2010-01-04
  • 打赏
  • 举报
回复
public interface ISerializable
{
void Serialize(Serializer xl, SerializeDirection direction);
}

要序列化的类 实现这个接口 然后再实现方法里把每个成员都调用上面抽象类的序列化

例如
xl.Serialize("dataContent", ref dataContent, dir);
xl.Serialize("messageList", messageList, dir);

SerializeDirection direction是序列化还是反序列化的枚举
yamakasi4050 2010-01-04
  • 打赏
  • 举报
回复
public abstract class Serializer
{
public Serializer()
{
}

/// <summary>
/// 把一个对象存入到流中,仅仅在序列化时被一次性调用。调用结束后,用户可以关闭流。必须重写。
/// </summary>
/// <param name="name"></param>
/// <param name="data"></param>
public virtual void Save(ISerializable data)
{
}

/// <summary>
/// 从流中加载一个对象,仅仅在序列化时被一次性调用。调用结束后,用户可以关闭流。必须重写。
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public virtual ISerializable Load()
{
return null;
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)字符串类型的变量,需重写
/// </summary>
/// <param name="name"></param>
/// <param name="val"></param>
public virtual void Serialize(string name, ref string val, Abis.Serialization.SerializeDirection direction)
{
}

public virtual void Serialize(string name, ref byte[] buffer, Abis.Serialization.SerializeDirection direction)
{
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)值类型的变量
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="val"></param>
protected void SerializeValue<T>(string name, ref T val, Abis.Serialization.SerializeDirection direction)
{
if (direction== SerializeDirection.LOAD)
{
string strVal = "";
Serialize(name, ref strVal, direction);
val = (T)Convert.ChangeType(strVal, typeof(T));
}
else
{
string strVal = val.ToString();
Serialize(name, ref strVal, direction);
}
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)枚举类型的变量
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="val"></param>
private void SerializeEnum<T>(string name, ref T val, Abis.Serialization.SerializeDirection direction)
{
if (!typeof(T).IsEnum)
{
throw new NotSupportedException("Serialize 'Enum' type error! val must be an Enum.");
}

if (direction == SerializeDirection.LOAD)
{
string text = string.Empty;
Serialize(name, ref text, direction);
val = (T)Enum.Parse(typeof(T), text);
}
else
{
string text = val.ToString();
Serialize(name, ref text, direction);
}
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)引用类型的变量,需重写
/// </summary>
/// <param name="name"></param>
/// <param name="val"></param>
protected virtual void SerializeObject(string name, ref ISerializable val, Abis.Serialization.SerializeDirection direction)
{

}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)泛型T类型的变量
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="val"></param>
public void Serialize<T>(string name, ref T val, Abis.Serialization.SerializeDirection direction)
{
if (typeof(T).IsEnum)
{
SerializeEnum(name, ref val, direction);
}
else if (typeof(T).IsValueType)
{
SerializeValue(name, ref val, direction);
}
else if (typeof(T).Equals(typeof(String)))
{
string strVal = string.Empty;
if (direction == SerializeDirection.SAVE) strVal = val.ToString();
this.Serialize(name, ref strVal, direction);
if (direction == SerializeDirection.LOAD) val = (T)Convert.ChangeType(strVal, typeof(T));
}
else //if (typeof(T).Equals(typeof(ISerializable)) || typeof(T).GetInterface("ISerializable")!=null)
{
ISerializable data = null;
if (direction != SerializeDirection.LOAD)
{
data = (ISerializable)val;
}

SerializeObject(name, ref data, direction);

//并行化时把取得的数据转换成正确的类型
if (direction == SerializeDirection.LOAD)
{
val = (T)data;
}
}
//else
//{
//throw new NotSupportedException("not supported type " + typeof(T).ToString());
//}
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)泛型T类型的列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <param name="val"></param>
public virtual void Serialize<T>(string name, List<T> val, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD)
{
int count = 0;
T data = default(T);
Serialize(name, ref count, direction);
for (int i = 0; i < count; i++)
{
Serialize("item" + i, ref data, direction);
val.Add(data);
}
}
else
{
int count = val.Count;
Serialize(name, ref count, direction);
for (int i = 0; i < val.Count; i++)
{
T data = val[i];
Serialize("item" + i, ref data, direction);
}
}
}

/// <summary>
/// 串行化(序列化)或并行化(反序列化)泛型类型的字典
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TVal"></typeparam>
/// <param name="name"></param>
/// <param name="val"></param>
public virtual void Serialize<TKey, TVal>(string name, Dictionary<TKey, TVal> val, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD) //少了一个枚举类型的判断
{
int count = 0;
int index = 0;
SerializeValue(name, ref count, direction);
while (index < count)
{
TKey key = default(TKey);
TVal data = default(TVal);
SerializeValue("item" + index + "_key", ref key, direction);

if (typeof(TVal).GetInterface("ISerializable") != null)
{
ISerializable temp = null;
SerializeObject("item" + index + "_value", ref temp, direction);
data = (TVal)temp;
}
else
{
SerializeValue("item" + index + "_value", ref data, direction);
}

val.Add(key, data);
index++;
}
}
else
{
int count = val.Count;
int index = 0;
SerializeValue(name, ref count, direction);
Dictionary<TKey,TVal>.Enumerator ENU = val.GetEnumerator();
while (ENU.MoveNext())
{
TKey key = ENU.Current.Key;
TVal data = ENU.Current.Value;
SerializeValue("item" + index + "_key", ref key, direction);
if(data is ISerializable)
{
ISerializable temp = (ISerializable)data;
SerializeObject("item" + index + "_value", ref temp, direction);
}
else
{
SerializeValue("item" + index + "_value", ref data, direction);
}

index++;
}
}
}

public void SerializeHex(string name, ref long val, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD)
{
string strVal = "";
Serialize(name, ref strVal, direction);
val = Convert.ToInt64(strVal, 16);
}
else
{
string strVal = "0x" + val.ToString("x");
Serialize(name, ref strVal, direction);
}
}

/// <summary>
/// 根据类型名创建实现ISerializable接口的对象
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
protected ISerializable createObject(string typeName)
{
Type type = Type.GetType(typeName);
System.Reflection.ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
if (ci == null) throw new Exception("The type "+typeName+" doesn't have no-parameter constructor.");
Object obj = ci.Invoke(null);
if (obj is ISerializable) return (ISerializable)obj;
else throw new Exception("Type " + typeName + " is not ISerializable");
}
}
yamakasi4050 2010-01-04
  • 打赏
  • 举报
回复
public class BinSerializer : Serializer
{
private Stream stream = null;
public BinSerializer(Stream s)
{
stream = s;
}

public override ISerializable Load()
{
ISerializable data = null;
SerializeObject("Data", ref data, SerializeDirection.LOAD);
return data;
}

public override void Save(ISerializable data)
{
SerializeObject("Data", ref data,SerializeDirection.SAVE);
}

protected override void SerializeObject(string name, ref ISerializable val, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD)
{
string typeName = readString();
if (typeName == "null")
{
val = null;
}
else
{
val = createObject(typeName);//------------?
val.Serialize(this, direction);
}
}
else
{
if (val == null)
{
writeString("null");
}
else
{
writeString(val.GetType().AssemblyQualifiedName);
}
val.Serialize(this, direction);
}
}

public override void Serialize(string name, ref string val, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD)
{
val = readString();
}
else
{
writeString(val);
}
}

public override void Serialize(string name, ref byte[] buffer, Abis.Serialization.SerializeDirection direction)
{
if (direction == SerializeDirection.LOAD)
{
buffer = readBytes();
}
else
{
writeBytes(buffer);
}
}

private byte[] readBytes()
{
byte[] buffer = new byte[4];
int len = stream.Read(buffer, 0, 4);
if (len == 4)
{
len = BitConverter.ToInt32(buffer, 0);
buffer = new byte[len];
stream.Read(buffer, 0, len);
return buffer;
}
else
{
return null;
}
}

private void writeBytes(byte[] buffer)
{
int len = buffer.Length;
stream.Write(BitConverter.GetBytes(len), 0, 4);
stream.Write(buffer, 0, buffer.Length);
}

private string readString()
{
byte[] lenBytes = new byte[4];
stream.Read(lenBytes, 0, 4);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] strBytes = new byte[len];
stream.Read(strBytes, 0, strBytes.Length);
return System.Text.Encoding.Unicode.GetString(strBytes);
}

private void writeString(string s)
{
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(s);
byte[] lenBytes = BitConverter.GetBytes(bytes.Length);//以字节数组的形式表示bytes.Length
stream.Write(lenBytes, 0, lenBytes.Length);//4
stream.Write(bytes, 0, bytes.Length);
}

}
qjf9013 2010-01-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yamakasi4050 的回复:]
自定义序列化 很麻烦
我是这样做的
把要序列化的对象的所有字段分拆序列化缓存,如果是复杂类型递归分拆,直到他是简单类型,最后就是处理枚举、值类型、字符串、其他不能再分拆的类型,前3个转二进制就不用说了,其他类型也按字符串处理,只不过他的类型也要用字符串表示下一起序列化。
[/Quote]有没有代码例子。 谢谢
yamakasi4050 2010-01-04
  • 打赏
  • 举报
回复
自定义序列化 很麻烦
我是这样做的
把要序列化的对象的所有字段分拆序列化缓存,如果是复杂类型递归分拆,直到他是简单类型,最后就是处理枚举、值类型、字符串、其他不能再分拆的类型,前3个转二进制就不用说了,其他类型也按字符串处理,只不过他的类型也要用字符串表示下一起序列化。
qjf9013 2010-01-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jimh 的回复:]
1,如果使用了MemoryStream作为序列化的输出,修改为FileStream,因为在内存不够的情况下死定的。
2,自己定制就没必要了,人家能反序列化吗?如果非要自己定制,那什么格式都可以,不一定是二进制序列化,反正到时候是自己读。
[/Quote]
首先谢谢你。定制可以说说么。首选二进制,因为二进制后的文件比较小,而且有一定加密性。 在数据量超过1亿的时候,序列化会出错貌似。
jimh 2010-01-04
  • 打赏
  • 举报
回复
1,如果使用了MemoryStream作为序列化的输出,修改为FileStream,因为在内存不够的情况下死定的。
2,自己定制就没必要了,人家能反序列化吗?如果非要自己定制,那什么格式都可以,不一定是二进制序列化,反正到时候是自己读。

111,120

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧