寻求一个快速系列化的方法,要求码流缩小到最低

cnwolfs 2011-12-14 08:08:54
寻求一个快速系列化的方法,要求码流缩小到最低
我看到的一个码流是使用EDI的方式,也就是分隔符的方式。这种方式的码流已经是非常小了。但是由于循环次数很多,因此速度不快,寻求较快的算法或者其它较好的系列化反系列化方法。

备注下:XML系列化是不可以的,码流太大,不适合我的应用场合,我的这个应用,宁可损失速度也不愿意增大码流。

以下代码是对DataTable进行系列化,仅对部分数据类型进行了支持。形成的报文格式大概是这样的
<DSRoot>
<DSHead>字段名1:类型名称 字段名2:类型名称 ...... 字段名n:类型名称</DSHead>
<DSBody>
<DSRow>字段值1 字段值2 ...... 字段值n</DSRow>
<DSRow>字段值1 字段值2 ...... 字段值n</DSRow>
<DSRow>字段值1 字段值2 ...... 字段值n</DSRow>
</DSBody>
</DSRoot>


public StringBuilder SerializeDS(System.Data.DataTable pDT)
{
try
{
StringBuilder mSB = new StringBuilder();
string mSplitChar = System.Text.Encoding.Default.GetString(new byte[] { 0x1E });

mSB.Append("<DSRoot>");
mSB.Append("<DSHead>");
if (pDT.Columns.Count > 0)
{
mSB.Append(pDT.Columns[0].ColumnName + ":" + pDT.Columns[0].DataType.Name);
for (int i = 1; i < pDT.Columns.Count; i++)
{
mSB.Append(mSplitChar + pDT.Columns[i].ColumnName + ":" + pDT.Columns[i].DataType.Name);
}
}
mSB.Append("</DSHead>");

mSB.Append("<DSBody>");
for (int i = 0; i < pDT.Rows.Count; i++)
{
mSB.Append("<DSRow>");
if (pDT.Columns.Count > 0)
{
mSB.Append(GetSerializeString(pDT.Columns[0].DataType, pDT.Rows[i][0]));
for (int j = 1; j < pDT.Columns.Count; j++)
{
mSB.Append(mSplitChar + GetSerializeString(pDT.Columns[j].DataType, pDT.Rows[i][j]));
}
}
mSB.Append("</DSRow>");
}
mSB.Append("</DSBody>");
mSB.Append("</DSRoot>");
return mSB;
}
catch (NullReferenceException NullEx)
{
throw NullEx;
}
catch (Exception Ex)
{
throw Ex;
}
}


private string GetSerializeString(Type pType, object pValue)
{
try
{

if (pType == typeof(System.String))
{
if (pValue != System.DBNull.Value)
{
return pValue.ToString();
}
else
{
return "";
}
}
else if (pType == typeof(System.DateTime))
{
try
{
if (pValue.ToString().Trim() != "")
{
return ((System.DateTime)pValue).ToString("yyyy-MM-dd HH:mm:ss");
}
else
{
return "1900-01-01";
}
}
catch
{
return "1900-01-01";
}
}
else if ((pType == typeof(System.Int32))
|| (pType == typeof(System.Int16))
|| (pType == typeof(System.UInt32))
|| (pType == typeof(System.UInt16))
|| (pType == typeof(System.Decimal))
|| (pType == typeof(System.Double))
)
{
try
{
if (pValue.ToString().Trim() != "")
{
return pValue.ToString();
}
else
{
return "0";
}
}
catch
{
return "0";
}
}
else if (pType == typeof(System.Boolean))
{
try
{
if (pValue.ToString().Trim() != "")
{
return ((bool)pValue).ToString();
}
else
{
return "false";
}
}
catch
{
return "false";
}
}
else if (pType == typeof(System.Guid))
{
try
{
if (pValue.ToString().Trim() != "")
{
return ((System.Guid)pValue).ToString();
}
else
{
return System.Guid.Empty.ToString();
}
}
catch
{
return System.Guid.Empty.ToString();
}
}
else if (pType == typeof(System.Byte))
{
try
{
if (pValue.ToString().Trim() != "")
{
return Convert.ToString(((Byte)pValue), 16).PadLeft(2, '0');
}
else
{
return "00";
}
}
catch
{
return "00";
}
}
else
{
try
{
return pValue.ToString();
}
catch
{
return "";
}
}
}
catch (NullReferenceException NullEx)
{
throw NullEx;
}
catch (Exception Ex)
{
throw Ex;
}
}





反系列化的代码就不贴了,同样是循环,对字符串进行分割。
寻求对这个代码改造,改成更快的,或者寻求其它低码流高速稳定的系列化方法。


...全文
183 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
chesi 2012-05-30
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 的回复:]

晕҉!҉又҉被҉删҉了҉一҉个҉回҉复҉。҉我҉倒҉要҉看҉看҉到҉底҉这҉个҉死҉东҉西҉是҉“҉机҉器҉人҉”҉还҉是҉c҉s҉d҉n҉雇҉的҉真҉人҉。҉
҉
҉我҉被҉删҉除҉的҉回҉复҉只҉有҉一҉句҉话҉:҉
҉
҉
҉你҉干҉脆҉删҉掉҉<҉D҉S҉R҉o҉o҉t҉>҉、҉<҉/҉D҉S҉R҉o҉o҉t҉>҉得҉了҉,҉那҉样҉“҉码҉流҉”҉更҉短҉。҉
[/Quote]

这个牛B了
cnwolfs 2012-02-17
  • 打赏
  • 举报
回复
这个帖好像乱了,我昨晚发了个回复也不见了,估计是数据库错误吧,不过帖子被抬起来了,我现在是使用分隔符形式的,但是要用反射搞定所有的数据类型有点小麻烦,还是希望能有个解决办法。
nonocast 2012-02-17
  • 打赏
  • 举报
回复
json->zip
cnwolfs 2012-02-17
  • 打赏
  • 举报
回复
看来要变成散分了
  • 打赏
  • 举报
回复
晕҉!҉又҉被҉删҉了҉一҉个҉回҉复҉。҉我҉倒҉要҉看҉看҉到҉底҉这҉个҉死҉东҉西҉是҉“҉机҉器҉人҉”҉还҉是҉c҉s҉d҉n҉雇҉的҉真҉人҉。҉
҉
҉我҉被҉删҉除҉的҉回҉复҉只҉有҉一҉句҉话҉:҉
҉
҉
҉你҉干҉脆҉删҉掉҉<҉D҉S҉R҉o҉o҉t҉>҉、҉<҉/҉D҉S҉R҉o҉o҉t҉>҉得҉了҉,҉那҉样҉“҉码҉流҉”҉更҉短҉。҉
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zdbb 的回复:]

象数据库存储一样定义,这样速度快码流小,缺点是自己处理比较复杂。
例如80年代的dbse,foxpro.
[/Quote]

dbase、foxpro是什么“码流”呢?

再问楼主,什么叫“码流”?字符串的别名?
  • 打赏
  • 举报
回复
你还搞什么“<DSRoot>、</DSRoot>”呢?这不是也大么?!
wanghui0380 2012-02-16
  • 打赏
  • 举报
回复
这个我们没有啥想法

具体需要测试在知道

通常想法
1.直接序列化并gzip
2.直接二进制序列化
3.json
4.直接序列化,同时把回车换行一类的东西去掉,并gzip
5.转成结构体,并用二进制保存这个结构体

这5种都是我们常用的手法,但是具体没测试过到底谁的字节最少,需要自己测试了
cnwolfs 2012-02-16
  • 打赏
  • 举报
回复
json 的码流也不小的,能有更好的选择没?
cnwolfs 2011-12-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 fangxinggood 的回复:]
直接用 json 呀,xml要开始要结束tag,这就多了很多无用的字了。

比如:
<person>
<name>test</name>
</person>

json是:
{name:"test"}

那么就是二进制序列化成binary了。
[/Quote]

json针对DataTable也是一样的,都是“要开始要结束tag”
机器人 2011-12-20
  • 打赏
  • 举报
回复
直接用 json 呀,xml要开始要结束tag,这就多了很多无用的字了。

比如:
<person>
<name>test</name>
</person>

json是:
{name:"test"}

那么就是二进制序列化成binary了。
stonespace 2011-12-20
  • 打赏
  • 举报
回复
如果想缩小码流,还不如直接序列化到二进制文件,xml码流肯定大,
足球中国 2011-12-20
  • 打赏
  • 举报
回复
??
fastserilizer国外的一个。是序列化的是二制制的值。感觉楼不是要这方面的。
cnwolfs 2011-12-20
  • 打赏
  • 举报
回复
JSON针对DataSet,DataTable等个头也不小啊,针对Entity实体类来说还可以接受,不过我自己做的EDI可以抛弃实体类中数据为默认值的或者为空的内容,统计起来,JSON也要在在EDI方式中的2倍以上的码流。


例如我对这个DataTable进行系列化

LineSignID LineSignName
Y 班轮
N 非班轮
H 核心班轮

得到的结果


"<DataTable xmlns=\"http:\/\/schemas.datacontract.org\/2004\/07\/System.Data\"><xs:schema id=\"NewDataSet\" xmlns:xs=\"http:\/\/www.w3.org\/2001\/XMLSchema\" xmlns=\"\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\"><xs:element name=\"NewDataSet\" msdata:IsDataSet=\"true\" msdata:MainDataTable=\"ShowModel\" msdata:UseCurrentLocale=\"true\"><xs:complexType><xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\"><xs:element name=\"ShowModel\"><xs:complexType><xs:sequence><xs:element name=\"LineSignID\" type=\"xs:string\" minOccurs=\"0\"\/><xs:element name=\"LineSignName\" type=\"xs:string\" minOccurs=\"0\"\/><\/xs:sequence><\/xs:complexType><\/xs:element><\/xs:choice><\/xs:complexType><\/xs:element><\/xs:schema><diffgr:diffgram xmlns:diffgr=\"urn:schemas-microsoft-com:xml-diffgram-v1\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\"><DocumentElement xmlns=\"\"><ShowModel diffgr:id=\"ShowModel1\" msdata:rowOrder=\"0\" diffgr:hasChanges=\"inserted\"><LineSignID>Y<\/LineSignID><LineSignName>班轮<\/LineSignName><\/ShowModel><ShowModel diffgr:id=\"ShowModel2\" msdata:rowOrder=\"1\" diffgr:hasChanges=\"inserted\"><LineSignID>N<\/LineSignID><LineSignName>非班轮<\/LineSignName><\/ShowModel><ShowModel diffgr:id=\"ShowModel3\" msdata:rowOrder=\"2\" diffgr:hasChanges=\"inserted\"><LineSignID>H<\/LineSignID><LineSignName>核心班轮<\/LineSignName><\/ShowModel><\/DocumentElement><\/diffgr:diffgram><\/DataTable>"


这个XML如果跟EDI方式对比的话,码流会是EDI的十几倍,EDI方式中,字段头仅占一行,也就是每个字段名列出一次,数据类型列出一次,另外都是数据了。

寻找了个LitJson的开源项目,发觉无法对DataTable进行系列化。

cnwolfs 2011-12-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 juliohuang 的回复:]
XML序列化后Gzip压缩,可以缩小10倍
[/Quote]

好像很多人支持这个,我最早使用的就是系列化成XML,然后用ZIP压缩,码流不见得小。压缩后的码流跟我这种EDI格式是差不多的,而且速度不见得快,如果用PC来说,时间基本都是忽略的,可是我的很多客户端是WinCE,压缩运算和XML系列化反系列化速度都不行,后来才取消这种模式的,目前使用EDI,至少来说,不压缩的情况下,速度还是比XML的路线快不少。

另外ZIP压缩之后会产生很多的特殊字符,例如0x00,0x10什么的,这些特殊字符在网络传输上需要处理,否则很容易出问题,因此使用Zip压缩之后,最好做个Base64编码,做完编码之后,码流就比EDI的大很多了。

因此,XML不合适,我在提问题的时候也说过了,不采纳这种方法。


JSON?不认识

哈夫曼编码?也不认识

说说看这两种是啥样

jiuhexuan 2011-12-14
  • 打赏
  • 举报
回复
思路:哈夫曼编码
sdl2005lyx 2011-12-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 juliohuang 的回复:]

XML序列化后Gzip压缩,可以缩小10倍
[/Quote]

这个建议不错。。。
特别 2011-12-14
  • 打赏
  • 举报
回复
看楼主的内容,还不如直接JSON呢,然后再ZIP一下,就差不多了
只在此山中 2011-12-14
  • 打赏
  • 举报
回复
象数据库存储一样定义,这样速度快码流小,缺点是自己处理比较复杂。
例如80年代的dbse,foxpro.
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 juliohuang 的回复:]
XML序列化后Gzip压缩,可以缩小10倍
[/Quote]
加载更多回复(1)

110,536

社区成员

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

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

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