分享一个高效的String分割类
最近在制定一个网络文件交互的协议,协议制订上采用了HTTP协议的方式,因此需对协议数据进行一个分割处理;虽然使用String的Split方法可以达到目的,但通过反编译查看其代码后发现实现相对复杂,性能上也不怎样;于是自己实现一个简单的字符分割处理类,在实现后和String的Sqlit方法进行了一个简单的对比,发现性能要比Sqlit高所以分享出来.
测试情况
- 分割处理的内容
Cache-Control:public, max-age=0
Content-Encoding:gzip
Content-Length:9480
Content-Type:text/html; charset=utf-8
Date:Wed, 31 Oct 2012 14:17:06 GMT
Expires:Wed, 31 Oct 2012 14:17:05 GMT
Last-Modified:Wed, 31 Oct 2012 14:17:05 GMT
P3P:CP=NON DSP COR ADM CUR DEV TAI OUR IND NAV PRE STA
P3P:CP=NON DSP COR ADM CUR DEV TAI OUR IND NAV PRE STA
Server:Microsoft-IIS/7.5
Set-Cookie:smark=Branch=default&IsProject=1; domain=.codeplex.com; expires=Fri, 31-Oct-2042 14:17:06 GMT; path=/
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:4.0
X-Powered-By:ASP.NET
- 测试分两部分,先是按/r/n进行的分割后,再进行属性侵害,具体测试代码如下:
static void StringSplit(string value) { for (int i = 0; i < count; i++) { value.Split(new string[] {"\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries); } } static void StringExtendSplit(string value) { for (int i = 0; i < count; i++) { Smark.StringExtend.Split(value, "\r\n\r\n"); } } static void StringToProperties(string value) { for (int i = 0; i < count; i++) { System.Collections.Hashtable properties = new System.Collections.Hashtable(8); string[] lines = value.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); int spindex; string pvalue; for (int k = 0; k < lines.Length; k++) { pvalue = lines[k]; spindex = pvalue.IndexOf(':'); properties[pvalue.Substring(0, spindex)] = pvalue.Substring(spindex + 1, pvalue.Length- spindex-1); } } } static void StringExtendToProperties(string value) { for (int i = 0; i < count; i++) { System.Collections.Hashtable properties= Smark.StringExtend.GetProperties(value,"\r\n\r\n",':'); } }
- 为了保证测试在跑之前都进行了预热运行
StringSplit(value); StringExtendSplit(value); StringExtendToProperties(value); StringToProperties(value); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Reset(); sw.Start(); StringSplit(value); sw.Stop(); Console.WriteLine("StringSplit:{0}ms", sw.Elapsed.TotalMilliseconds); sw.Reset(); sw.Start(); StringExtendSplit(value); sw.Stop(); Console.WriteLine("StringExtendSplit:{0}ms", sw.Elapsed.TotalMilliseconds); sw.Reset(); sw.Start(); StringToProperties(value); sw.Stop(); Console.WriteLine("StringToProperties:{0}ms", sw.Elapsed.TotalMilliseconds); sw.Reset(); sw.Start(); StringExtendToProperties(value); sw.Stop(); Console.WriteLine("StringExtendToProperties:{0}ms", sw.Elapsed.TotalMilliseconds);
- 10000次的处理结果
Release 执行Exe的测试结果来看单是Split方法就比String.Split方法高出一倍的性能.即使是进一步属性的分割也比一个String.Split高效出一倍,在处理了两次分割效率依然没有多少的损失.
- 完整代码
using System; using System.Collections.Generic; using System.Collections; using System.Text; namespace Smark { /// <summary> /// Copyright © henryfan 2012 /// Email: henryfan@msn.com /// HomePage: http://www.ikende.com /// CreateTime: 2012/11/1 21:36:19 /// </summary> public class StringExtend { public static int DefaultResultLength = 8; public static IList<string> Split(byte[] data, Encoding coding, int start, int count, string splitdata) { return Split(coding.GetString(data, start, count), splitdata); } public static IList<string> Split(string value, string splitdata) { List<string> result = new List<string>(DefaultResultLength); int startIndex = 0; bool eq = false; int sindex = 0; int splitlength = splitdata.Length; int datalength = value.Length; while (sindex < value.Length) { eq = true; for (int k = 0; k < splitlength; k++) { if (value[sindex + k] != splitdata[k]) { eq = false; break; } } if (eq) { sindex += splitlength; if (sindex - splitlength > startIndex) result.Add(value.Substring(startIndex, sindex - startIndex - splitlength)); startIndex = sindex; } else { sindex++; } } if (startIndex < datalength) { if (sindex - splitlength > startIndex) result.Add(value.Substring(startIndex, datalength - startIndex)); } return result; } public static Hashtable GetProperties(string value, string linesplit, char propertysplit) { Hashtable result = new Hashtable(DefaultResultLength); int splitlength = linesplit.Length; int startIndex = 0; bool eq = false; int sindex = 0; int propertyindex = 0; while (sindex < value.Length) { eq = true; if (propertyindex == 0 && value[sindex] == propertysplit) propertyindex = sindex; for (int k = 0; k < splitlength; k++) { if (value[sindex + k] != linesplit[k]) { eq = false; break; } } if (eq) { if (sindex > startIndex) { result[value.Substring(startIndex, propertyindex - startIndex)] = value.Substring(propertyindex + 1, sindex - propertyindex); } sindex += splitlength; propertyindex = 0; startIndex = sindex; } else { sindex++; } } if (startIndex < value.Length) { result[value.Substring(startIndex, propertyindex - startIndex)] = value.Substring(propertyindex + 1, sindex - propertyindex); } return result; } public static Hashtable GetProperties(byte[] data, Encoding coding, int start, int count, string linesplit, char propertysplit) { return GetProperties(coding.GetString(data, start, count), linesplit, propertysplit); } } }