C# 二进制替换第二弹 二进制替换深入研究---List 与byte[] 效率对比 byte[] 数组 替换

上一章节,中提供了简单可以替换的例子,在本节中,进行了bug修改并且对不同方式进行了效率测试


测试用的代码

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #region 性能对比  
  2.         protected void  二进制数据替换()  
  3.         {  
  4.             string sourcestr = "68 30 55 08 67 30 55 16 33 16";  
  5.             //string oldstr = "30";  
  6.             //string newvalstr = "FA FA FA";  
  7.   
  8.             string oldstr = "FA FA FA";  
  9.             string newvalstr = "30";  
  10.   
  11.             byte[] source = sourcestr.Replace(" """).HexToByteArray();  
  12.             //"68 12 00 12 00 68 8D DE 00 00 00 00 0D 62 01 00 68 30 30 34 73 42 31 30 ED 16".Replace(" ", "").HexToByteArray();  
  13.             byte[] old = oldstr.Replace(" """).HexToByteArray();  
  14.             byte[] newval = newvalstr.Replace(" """).HexToByteArray();  
  15.   
  16.             byte[] result = HexUtility.Replace(source, old, newval);  
  17.             string strs = result.ByteArray2HexString();  
  18.             var sb = strs.Replace(" "string.Empty) == sourcestr.Replace(oldstr, newvalstr).Replace(" """);  
  19.             if (!sb)  
  20.             {  
  21.                 var d = "替换结果不正确";  
  22.             }  
  23.   
  24.             var listRep = strs == source.ReplaceA(old, newval).ByteArray2HexString();  
  25.   
  26.   
  27.   
  28.             //全部替换  
  29.             result = HexUtility.Replace(source, new List<HexReplaceEntity>()  
  30.                                                    {  
  31.                                                        new HexReplaceEntity()  
  32.                                                            {  
  33.                                                                oldValue = "68".Replace(" """).HexToByteArray(),  
  34.                                                                newValue = "67 02".Replace(" """).HexToByteArray(),  
  35.                                                            }  
  36.                                                            ,  
  37.                                                           new HexReplaceEntity()  
  38.                                                            {  
  39.                                                                oldValue = "67".Replace(" """).HexToByteArray(),  
  40.                                                                newValue = "67 01".Replace(" """).HexToByteArray(),  
  41.                                                            },  
  42.                                                           new HexReplaceEntity()  
  43.                                                            {  
  44.                                                                oldValue = "16".Replace(" """).HexToByteArray(),  
  45.                                                                newValue = "67 03".Replace(" """).HexToByteArray(),  
  46.                                                            },  
  47.                                                    });  
  48.             string str2 = result.ByteArray2HexString();  
  49.             //字符串替换检查  
  50.             if (str2.Replace(" "string.Empty) != sourcestr  
  51.                 .Replace("67""67 01")  
  52.                  .Replace("68""67 02")  
  53.                  .Replace("16""67 03")  
  54.                 .Replace(" "string.Empty)  
  55.                 )  
  56.             {  
  57.   
  58.                 var d1 = "替换结果不正确";  
  59.   
  60.             }  
  61.   
  62.   
  63.             string restx = HexUtility.Replace(result, "67 01".Replace(" """).HexToByteArray(), "67".Replace(" """).HexToByteArray()).ByteArray2HexString();  
  64.   
  65.             result = HexUtility.Replace(result, new List<HexReplaceEntity>()  
  66.                                                    {  
  67.                                                        new HexReplaceEntity()  
  68.                                                            {  
  69.                                                                oldValue = "67 02".Replace(" """).HexToByteArray(),  
  70.                                                                newValue = "68".Replace(" """).HexToByteArray(),  
  71.                                                            }  
  72.                                                            ,  
  73.                                                           new HexReplaceEntity()  
  74.                                                            {  
  75.                                                                oldValue = "67 01".Replace(" """).HexToByteArray(),  
  76.                                                                newValue = "67".Replace(" """).HexToByteArray(),  
  77.                                                            },  
  78.                                                           new HexReplaceEntity()  
  79.                                                            {  
  80.                                                                oldValue = "67 03".Replace(" """).HexToByteArray(),  
  81.                                                                newValue = "16".Replace(" """).HexToByteArray(),  
  82.                                                            },  
  83.                                                    });  
  84.   
  85.             string rel = result.ByteArray2HexString();  
  86.             //字符串替换检查  
  87.             if (rel.Replace(" "string.Empty) != sourcestr  
  88.                 .Replace("67 01""67")  
  89.                  .Replace("67 02""68")  
  90.                  .Replace("67 03""16")  
  91.                 .Replace(" "string.Empty)  
  92.                 )  
  93.             {  
  94.   
  95.                 var d2 = "替换结果不正确";  
  96.   
  97.             }  
  98.         }  
  99.         protected void 二进制数据替换数组复制与List效率对比()  
  100.         {  
  101.             string sourcestr = "68 30 55 08 67 30 55 16 33 16 68 39 00 39 00 68 C2 DE 00 00 00 00 0C 6D 08 00 01 04 29 00 00 01 00 01 09 04 00 19 44 00 00 02 00 14 03 11 18 24 25 00 01 01 11 42 46 01 48 43 03 01 95 99 00 00 00 00 00 00 00 00 00 00 28 C7 16 68 39 00 39 00 68 C2 DE 00 00 00 00 0C 6D 08 00 01 04 29 00 00 01 00 01 09 04 00 19 44 00 00 02 00 14 03 11 18 24 25 00 01 01 11 42 46 01 48 43 03 01 95 99 00 00 00 00 00 00 00 00 00 00 28 C7 16 68 39 00 39 00 68 C2 DE 00 00 00 00 0C 6D 08 00 01 04 29 00 00 01 00 01 09 04 00 19 44 00 00 02 00 14 03 11 18 24 25 00 01 01 11 42 46 01 48 43 03 01 95 99 00 00 00 00 00 00 00 00 00 00 28 C7 16";  
  102.             string oldstr = "30";  
  103.             string newvalstr = "FA FA FA";  
  104.   
  105.             //string oldstr = "FA FA FA";  
  106.             //string newvalstr = "30";  
  107.   
  108.             byte[] source = sourcestr.Replace(" """).HexToByteArray();  
  109.             //"68 12 00 12 00 68 8D DE 00 00 00 00 0D 62 01 00 68 30 30 34 73 42 31 30 ED 16".Replace(" ", "").HexToByteArray();  
  110.             byte[] old = oldstr.Replace(" """).HexToByteArray();  
  111.             byte[] newval = newvalstr.Replace(" """).HexToByteArray();  
  112.   
  113.   
  114.   
  115.             //100万次计算  
  116.             var arr = System.Linq.Enumerable.Range(1, 1000000);  
  117.   
  118.             //方法1  
  119.             Action act = () => { foreach (var k in arr) { source.Replace(old, newval); } };  
  120.   
  121.             //方法2  
  122.             Action act2 = () => { foreach (var k in arr) { source.ReplaceA(old, newval); } };  
  123.   
  124.             //array 用时1828  
  125.             System.Diagnostics.Debug.WriteLine("array 用时" + Stopwatch(act));  
  126.             //list 用时2481  
  127.             System.Diagnostics.Debug.WriteLine("list 用时" + Stopwatch(act2));  
  128.   
  129.   
  130.         }  
  131.   
  132.         /// <summary>  
  133.         /// 测试运行时间  
  134.         /// </summary>  
  135.         /// <param name="method">需要执行的方法</param>  
  136.         /// <param name="summary">对方法的说明</param>  
  137.         /// <returns>返回,这个方法执行用了多少毫秒</returns>  
  138.         public static long Stopwatch(Action method)  
  139.         {  
  140.             System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();  
  141.             watch.Restart();  
  142.             //运行方法  
  143.             method.Invoke();  
  144.   
  145.             watch.Stop();  
  146.              
  147.             return watch.ElapsedMilliseconds;  
  148.         }  
  149.         /// <summary>  
  150.         /// 测试运行时间  
  151.         /// </summary>  
  152.         /// <param name="method">需要执行的方法</param>  
  153.         /// <param name="obj">参数对像</param>  
  154.         /// <returns>返回,这个方法执行用了多少毫秒</returns>  
  155.         public static long Stopwatch<T>(Action<T> method, T obj)  
  156.         {  
  157.             return Stopwatch(new Action(() =>  
  158.             {  
  159.                 method.Invoke(obj);  
  160.             }));  
  161.         }  
  162.  
  163.         #endregion  

hextobytearray() 是效字符串转换成为二进制数据


替换核心代码


[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /// <summary>  
  2.   /// 二进制数据 操作,对单个数组替换时,如果新值长度小于旧值长度时出现的问题进行了修改  
  3.   /// </summary>  
  4.   public static class HexUtility  
  5.   {  
  6.       /// <summary>  
  7.       /// 二进制替换,如果没有替换则返回原数组对像的复本.比使用List效率高25%  
  8.       /// </summary>  
  9.       /// <param name="sourceByteArray">源数据</param>  
  10.       /// <param name="oldValue">需要替换的数据</param>  
  11.       /// <param name="newValue">将要替换成为的数据</param>  
  12.       public static byte[] Replace(this byte[] sourceByteArray, byte[] oldValue, byte[] newValue)  
  13.       {  
  14.           //创建新数据多出1字节  
  15.           int newArrayLen = (int)((newValue.Length / (double)oldValue.Length) * sourceByteArray.Length) + 1;  
  16.           //得到数组长度  
  17.           newArrayLen = Math.Max(newArrayLen, sourceByteArray.Length);  
  18.           //新的最后结果数组  
  19.           byte[] newByteArray = new byte[newArrayLen];  
  20.           //新数组的当前索引  
  21.           int curIndex = 0;  
  22.           //开始结束  
  23.           int start = -1;  
  24.           int end = -1;  
  25.           //当前查找到的索引  
  26.           int oldCurindex = 0;  
  27.           //替换数据替换  
  28.           for (int x = 0; x < sourceByteArray.Length; x++)  
  29.           {  
  30.               newByteArray[curIndex] = sourceByteArray[x];  
  31.               curIndex++;  
  32.               //查找要替换的数据  
  33.               if (sourceByteArray[x] == oldValue[oldCurindex])  
  34.               {  
  35.                   if (oldCurindex == 0)  
  36.                   {  
  37.                       start = x;  
  38.                   }  
  39.                   if (oldCurindex == oldValue.Length - 1)  
  40.                   {  
  41.                       end = x;  
  42.                       oldCurindex = 0;  
  43.                   }  
  44.                   else  
  45.                   {  
  46.                       oldCurindex++;  
  47.                   }  
  48.               }  
  49.               else  
  50.               {  
  51.                   oldCurindex = 0;  
  52.               }  
  53.               //数据查找完成  
  54.               if (start != -1 && end != -1)  
  55.               {  
  56.                   if (curIndex > 0)  
  57.                   {  
  58.                       curIndex -= 1;  
  59.                   }  
  60.                   curIndex -= end - start;  
  61.   
  62.                   //复制替换数据  
  63.                   Buffer.BlockCopy(newValue, 0, newByteArray, curIndex, newValue.Length);  
  64.                   //计算新数组的偏移量  
  65.                   curIndex += newValue.Length;  
  66.                   //重新设置需要复制索引的索引  
  67.                   start = end = -1;  
  68.               }  
  69.           }  
  70.   
  71.           //处理返回结果  
  72.           byte[] result = null;  
  73.           if (curIndex != 0)  
  74.           {  
  75.               result = new byte[curIndex];  
  76.               Buffer.BlockCopy(newByteArray, 0, result, 0, result.Length);  
  77.           }  
  78.           else  
  79.           {  
  80.               result = new byte[sourceByteArray.Length];  
  81.               Buffer.BlockCopy(sourceByteArray, 0, result, 0, result.Length);  
  82.           }  
  83.           return result;  
  84.       }  
  85.   
  86.       /// <summary>  
  87.       /// 二进制替换,如果没有替换则返回原数组对像的复本.  
  88.       /// </summary>  
  89.       /// <param name="sourceByteArray">源数据</param>  
  90.       /// <param name="replaces">需要替换的数据集合</param>  
  91.       public static byte[] Replace(this byte[] sourceByteArray, List<HexReplaceEntity> replaces)  
  92.       {  
  93.           //创建新数据多出1字节  
  94.           int newArrayLen = (int)((replaces.Sum(p => p.newValue.Length) / (double)replaces.Sum(p => p.oldValue.Length)) * sourceByteArray.Length) + 1;  
  95.           //得到数组长度  
  96.           newArrayLen = Math.Max(newArrayLen, sourceByteArray.Length);  
  97.           //新的最后结果数组  
  98.           byte[] newByteArray = new byte[newArrayLen];  
  99.           //新数组的当前索引  
  100.           int curIndex = 0;  
  101.           bool find = false;  
  102.           //替换数据替换  
  103.           for (int x = 0; x < sourceByteArray.Length; x++)  
  104.           {  
  105.   
  106.               foreach (HexReplaceEntity rep in replaces)  
  107.               {  
  108.                   //查找要替换的数据  
  109.                   if (sourceByteArray[x] == rep.oldValue[rep.oldCurindex])  
  110.                   {  
  111.                       if (rep.oldCurindex == 0)  
  112.                       {  
  113.                           rep.start = x;  
  114.                       }  
  115.                       if (rep.oldCurindex == rep.oldValue.Length - 1)  
  116.                       {  
  117.                           rep.end = x;  
  118.                           rep.oldCurindex = 0;  
  119.                       }  
  120.                       else  
  121.                       {  
  122.                           rep.oldCurindex++;  
  123.                       }  
  124.                   }  
  125.                   else  
  126.                   {  
  127.                       rep.oldCurindex = 0;  
  128.                       newByteArray[curIndex] = sourceByteArray[x];  
  129.                       find = false;  
  130.                   }  
  131.                   //数据查找完成  
  132.                   if (rep.start != -1 && rep.end != -1)  
  133.                   {  
  134.                       find = true;  
  135.                       if (rep.newValue.Length >= rep.oldValue.Length)  
  136.                       {  
  137.                           //复制替换数据  
  138.                           Buffer.BlockCopy(rep.newValue, 0, newByteArray, curIndex, rep.newValue.Length);  
  139.                           //计算新数组的偏移量  
  140.                           curIndex += rep.newValue.Length;  
  141.                       }  
  142.                       else  
  143.                       //由大字节替换为少字节时出现了问题  
  144.                       {  
  145.                           curIndex -= rep.end - rep.start;  
  146.                           //复制替换数据  
  147.                           Buffer.BlockCopy(rep.newValue, 0, newByteArray, curIndex, rep.newValue.Length);  
  148.                           //计算新数组的偏移量  
  149.                           curIndex += rep.newValue.Length;  
  150.                       }  
  151.                       //重新设置需要复制索引的索引  
  152.                       rep.start = rep.end = -1;  
  153.                       break;  
  154.                   }  
  155.               }  
  156.               if (!find)  
  157.               {  
  158.                   curIndex++;  
  159.               }  
  160.           }  
  161.   
  162.           //处理返回结果  
  163.           byte[] result = null;  
  164.           if (curIndex != 0)  
  165.           {  
  166.               result = new byte[curIndex];  
  167.               Buffer.BlockCopy(newByteArray, 0, result, 0, result.Length);  
  168.           }  
  169.           else  
  170.           {  
  171.               result = new byte[sourceByteArray.Length];  
  172.               Buffer.BlockCopy(sourceByteArray, 0, result, 0, result.Length);  
  173.           }  
  174.           return result;  
  175.       }  
  176.   
  177.       /// <summary>  
  178.       /// 二进制替换,如果没有替换则返回原数组对像的复本. 内部使用List,比直接用数组替换效率低25%  
  179.       /// </summary>  
  180.       /// <param name="sourceByteArray">源数据</param>  
  181.       ///   
  182.       /// </summary>  
  183.       /// <param name="oldValue">需要替换的数据</param>  
  184.       /// <param name="newValue">将要替换成为的数据</param>  
  185.       public static byte[] ReplaceA(this byte[] sourceByteArray, byte[] oldValue, byte[] newValue)  
  186.       {  
  187.           //创建新数据多出1字节  
  188.           int newArrayLen = (int)((newValue.Length / (double)oldValue.Length) * sourceByteArray.Length) + 1;  
  189.           //得到数组长度  
  190.           newArrayLen = Math.Max(newArrayLen, sourceByteArray.Length);  
  191.           int oldCurindex = 0;  
  192.           List<byte> result = new List<byte>(newArrayLen);  
  193.           //替换数据替换  
  194.           for (int x = 0; x < sourceByteArray.Length; x++)  
  195.           {  
  196.               var b = sourceByteArray[x];  
  197.               result.Add(b);  
  198.               if (b == oldValue[oldCurindex])  
  199.               {  
  200.                   if (oldCurindex == oldValue.Length - 1)  
  201.                   {  
  202.                       oldCurindex = 0;  
  203.                       //称除现有数据  
  204.                       for (int k = 0; k < oldValue.Length; k++)  
  205.                       {  
  206.                           result.RemoveAt(result.Count - 1);  
  207.                       }  
  208.                       //添加新数据  
  209.                       result.AddRange(newValue);  
  210.                   }  
  211.                   else  
  212.                   {  
  213.                       oldCurindex++;  
  214.                   }  
  215.               }  
  216.           }  
  217.           byte[] resultarr = result.ToArray();  
  218.           result.Clear();  
  219.           result = null;  
  220.           return resultarr;  
  221.   
  222.       }  
  223.   
  224.   }  
  225.   
  226.   /// <summary>  
  227.   /// 替换用的数据实体  
  228.   /// </summary>  
  229.   public class HexReplaceEntity  
  230.   {  
  231.       /// <summary>  
  232.       /// 需要替换的原始值  
  233.       /// </summary>  
  234.       public byte[] oldValue { getset; }  
  235.   
  236.       /// <summary>  
  237.       /// 新值  
  238.       /// </summary>  
  239.       public byte[] newValue { getset; }  
  240.   
  241.       /// <summary>  
  242.       /// 默认开始结束标记  
  243.       /// </summary>  
  244.       internal int start = -1;  
  245.       /// <summary>  
  246.       /// 默认开始结束标记  
  247.       /// </summary>  
  248.       internal int end = -1;  
  249.   
  250.       //当前查找到的索引  
  251.       internal int oldCurindex = 0;  
  252.   
  253.   }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值