SoftBasic.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Newtonsoft.Json.Linq;
  6. using System.Windows.Forms;
  7. using System.IO;
  8. using System.Runtime.Serialization.Formatters.Binary;
  9. using System.Security.Cryptography;
  10. using System.Drawing;
  11. namespace HslCommunication.BasicFramework
  12. {
  13. /// <summary>
  14. /// 一个软件基础类,提供常用的一些静态方法
  15. /// </summary>
  16. public class SoftBasic
  17. {
  18. #region MD5码计算块
  19. /// <summary>
  20. /// 获取文件的md5码
  21. /// </summary>
  22. /// <param name="filePath"></param>
  23. /// <returns></returns>
  24. public static string CalculateFileMD5(string filePath)
  25. {
  26. string str_md5 = string.Empty;
  27. using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  28. {
  29. str_md5 = CalculateStreamMD5(fs);
  30. }
  31. return str_md5;
  32. }
  33. /// <summary>
  34. /// 获取数据流的md5码
  35. /// </summary>
  36. /// <param name="stream">数据流,可以是内存流,也可以是文件流</param>
  37. /// <returns></returns>
  38. public static string CalculateStreamMD5(Stream stream)
  39. {
  40. MD5 md5 = new MD5CryptoServiceProvider();
  41. byte[] bytes_md5 = md5.ComputeHash(stream);
  42. return BitConverter.ToString(bytes_md5).Replace("-", "");
  43. }
  44. /// <summary>
  45. /// 获取内存图片的md5码
  46. /// </summary>
  47. /// <param name="bitmap">内存图片</param>
  48. /// <returns></returns>
  49. public static string CalculateStreamMD5(Bitmap bitmap)
  50. {
  51. MemoryStream ms = new MemoryStream();
  52. bitmap.Save(ms, bitmap.RawFormat);
  53. MD5 md5 = new MD5CryptoServiceProvider();
  54. byte[] bytes_md5 = md5.ComputeHash(ms);
  55. ms.Dispose();
  56. return BitConverter.ToString(bytes_md5).Replace("-", "");
  57. }
  58. #endregion
  59. #region 数据大小相关
  60. /// <summary>
  61. /// 从一个字节大小返回带单位的描述
  62. /// </summary>
  63. /// <param name="size"></param>
  64. /// <returns></returns>
  65. public static string GetSizeDescription(long size)
  66. {
  67. if (size < 1000)
  68. {
  69. return size + " B";
  70. }
  71. else if (size < 1000 * 1000)
  72. {
  73. float data = (float)size / 1024;
  74. return data.ToString("F2") + " Kb";
  75. }
  76. else if (size < 1000 * 1000 * 1000)
  77. {
  78. float data = (float)size / 1024 / 1024;
  79. return data.ToString("F2") + " Mb";
  80. }
  81. else
  82. {
  83. float data = (float)size / 1024 / 1024 / 1024;
  84. return data.ToString("F2") + " Gb";
  85. }
  86. }
  87. #endregion
  88. #region 数组处理方法
  89. /// <summary>
  90. /// 一个通用的数组新增个数方法,会自动判断越界情况,越界的情况下,会自动的截断或是填充
  91. /// </summary>
  92. /// <typeparam name="T">数据类型</typeparam>
  93. /// <param name="array">原数据</param>
  94. /// <param name="data">等待新增的数据</param>
  95. /// <param name="max">原数据的最大值</param>
  96. public static void AddArrayData<T>( ref T[] array, T[] data, int max )
  97. {
  98. if (data == null) return; // 数据为空
  99. if (data.Length == 0) return; // 数据长度为空
  100. if (array.Length == max)
  101. {
  102. for (int i = 0; i < array.Length - data.Length; i++)
  103. {
  104. array[i] = array[i + 1];
  105. }
  106. for (int i = 0; i < data.Length; i++)
  107. {
  108. array[array.Length - data.Length + i] = data[i];
  109. }
  110. }
  111. else
  112. {
  113. if ((array.Length + data.Length) > max)
  114. {
  115. T[] tmp = new T[max];
  116. for (int i = 0; i < (max - data.Length); i++)
  117. {
  118. tmp[i] = array[i + (array.Length - max + data.Length)];
  119. }
  120. for (int i = 0; i < data.Length; i++)
  121. {
  122. tmp[tmp.Length - data.Length + i] = data[i];
  123. }
  124. // 更新数据
  125. array = tmp;
  126. }
  127. else
  128. {
  129. T[] tmp = new T[array.Length + data.Length];
  130. for (int i = 0; i < array.Length; i++)
  131. {
  132. tmp[i] = array[i];
  133. }
  134. for (int i = 0; i < data.Length; i++)
  135. {
  136. tmp[tmp.Length - data.Length + i] = data[i];
  137. }
  138. array = tmp;
  139. }
  140. }
  141. }
  142. /// <summary>
  143. /// 将一个数组进行扩充到指定长度,或是缩短到指定长度
  144. /// </summary>
  145. /// <typeparam name="T">数组的类型</typeparam>
  146. /// <param name="data">原先数据的数据</param>
  147. /// <param name="length">新数组的长度</param>
  148. /// <returns>新数组长度信息</returns>
  149. public static T[] ArrayExpandToLength<T>( T[] data, int length )
  150. {
  151. if (data == null) return new T[length];
  152. if (data.Length == length) return data;
  153. T[] buffer = new T[length];
  154. Array.Copy( data, buffer, Math.Min( data.Length, buffer.Length ) );
  155. return buffer;
  156. }
  157. /// <summary>
  158. /// 将一个数组进行扩充到偶数长度
  159. /// </summary>
  160. /// <typeparam name="T">数组的类型</typeparam>
  161. /// <param name="data">原先数据的数据</param>
  162. /// <returns>新数组长度信息</returns>
  163. public static T[] ArrayExpandToLengthEven<T>( T[] data )
  164. {
  165. if (data == null) return new T[0];
  166. if (data.Length % 2 == 1)
  167. {
  168. return ArrayExpandToLength( data, data.Length + 1 );
  169. }
  170. else
  171. {
  172. return data;
  173. }
  174. }
  175. #endregion
  176. #region 数组比较
  177. /// <summary>
  178. /// 判断两个字节的指定部分是否相同
  179. /// </summary>
  180. /// <param name="b1">第一个字节</param>
  181. /// <param name="start1">第一个字节的起始位置</param>
  182. /// <param name="b2">第二个字节</param>
  183. /// <param name="start2">第二个字节的起始位置</param>
  184. /// <param name="length">校验的长度</param>
  185. /// <returns>返回是否相等</returns>
  186. /// <exception cref="IndexOutOfRangeException"></exception>
  187. public static bool IsTwoBytesEquel(byte[] b1, int start1, byte[] b2, int start2, int length)
  188. {
  189. if (b1 == null || b2 == null) return false;
  190. for (int i = 0; i < length; i++)
  191. {
  192. if (b1[i + start1] != b2[i + start2])
  193. {
  194. return false;
  195. }
  196. }
  197. return true;
  198. }
  199. /// <summary>
  200. /// 判断两个数据的令牌是否相等
  201. /// </summary>
  202. /// <param name="head">字节数据</param>
  203. /// <param name="token">GUID数据</param>
  204. /// <returns>返回是否相等</returns>
  205. public static bool IsByteTokenEquel(byte[] head, Guid token)
  206. {
  207. return IsTwoBytesEquel(head, 12, token.ToByteArray(), 0, 16);
  208. }
  209. /// <summary>
  210. /// 判断两个数据的令牌是否相等
  211. /// </summary>
  212. /// <param name="token1">第一个令牌</param>
  213. /// <param name="token2">第二个令牌</param>
  214. /// <returns>返回是否相等</returns>
  215. public static bool IsTwoTokenEquel(Guid token1, Guid token2)
  216. {
  217. return IsTwoBytesEquel(token1.ToByteArray(), 0, token2.ToByteArray(), 0, 16);
  218. }
  219. #endregion
  220. #region 枚举相关块
  221. /// <summary>
  222. /// 获取一个枚举类型的所有枚举值,可直接应用于组合框数据
  223. /// </summary>
  224. /// <typeparam name="TEnum">枚举的类型值</typeparam>
  225. /// <returns>枚举值数组</returns>
  226. public static TEnum[] GetEnumValues<TEnum>() where TEnum : struct
  227. {
  228. return (TEnum[])Enum.GetValues(typeof(TEnum));
  229. }
  230. #endregion
  231. #region JSON数据提取相关块
  232. /// <summary>
  233. /// 一个泛型方法,提供json对象的数据读取
  234. /// </summary>
  235. /// <typeparam name="T">读取的泛型</typeparam>
  236. /// <param name="json">json对象</param>
  237. /// <param name="value_name">值名称</param>
  238. /// <param name="default_value">默认值</param>
  239. /// <returns></returns>
  240. public static T GetValueFromJsonObject<T>(JObject json, string value_name, T default_value)
  241. {
  242. //if (json.Property(value_name) != null)
  243. //{
  244. // return json.Property(value_name).Value.Value<T>();
  245. //}
  246. //else
  247. //{
  248. // return default_value;
  249. //}
  250. return default_value;
  251. }
  252. /// <summary>
  253. /// 一个泛型方法,提供json对象的数据写入
  254. /// </summary>
  255. /// <typeparam name="T">写入的泛型</typeparam>
  256. /// <param name="json">json对象</param>
  257. /// <param name="property">值名称</param>
  258. /// <param name="value">值数据</param>
  259. public static void JsonSetValue<T>(JObject json, string property, T value)
  260. {
  261. if (json.Property(property) != null)
  262. {
  263. json.Property(property).Value = new JValue(value);
  264. }
  265. else
  266. {
  267. json.Add(property, new JValue(value));
  268. }
  269. }
  270. #endregion
  271. #region 异常错误信息格式化
  272. /// <summary>
  273. /// 显示一个完整的错误信息
  274. /// </summary>
  275. /// <param name="ex">异常对象</param>
  276. /// <exception cref="NullReferenceException"></exception>
  277. public static void ShowExceptionMessage(Exception ex)
  278. {
  279. MessageBox.Show(GetExceptionMessage(ex));
  280. }
  281. /// <summary>
  282. /// 显示一个完整的错误信息,和额外的字符串描述信息
  283. /// </summary>
  284. /// <param name="extraMsg">额外的描述信息</param>
  285. /// <param name="ex">异常对象</param>
  286. /// <exception cref="NullReferenceException"></exception>
  287. public static void ShowExceptionMessage(string extraMsg, Exception ex)
  288. {
  289. MessageBox.Show(GetExceptionMessage(extraMsg, ex));
  290. }
  291. /// <summary>
  292. /// 获取一个异常的完整错误信息
  293. /// </summary>
  294. /// <param name="ex">异常对象</param>
  295. /// <returns></returns>
  296. /// <exception cref="NullReferenceException"></exception>
  297. public static string GetExceptionMessage(Exception ex)
  298. {
  299. return StringResources.ExceptionMessage + ex.Message + Environment.NewLine +
  300. StringResources.ExceptionStackTrace + ex.StackTrace + Environment.NewLine +
  301. StringResources.ExceptopnTargetSite + ex.TargetSite;
  302. }
  303. /// <summary>
  304. /// 获取一个异常的完整错误信息,和额外的字符串描述信息
  305. /// </summary>
  306. /// <param name="extraMsg">额外的信息</param>
  307. /// <param name="ex">异常对象</param>
  308. /// <returns></returns>
  309. /// <exception cref="NullReferenceException"></exception>
  310. public static string GetExceptionMessage(string extraMsg, Exception ex)
  311. {
  312. if (string.IsNullOrEmpty(extraMsg))
  313. {
  314. return GetExceptionMessage(ex);
  315. }
  316. else
  317. {
  318. return extraMsg + Environment.NewLine + GetExceptionMessage(ex);
  319. }
  320. }
  321. #endregion
  322. #region Hex字符串和Byte[]相互转化块
  323. /// <summary>
  324. /// 字节数据转化成16进制表示的字符串
  325. /// </summary>
  326. /// <param name="InBytes">字节数组</param>
  327. /// <returns>返回的字符串</returns>
  328. /// <exception cref="NullReferenceException"></exception>
  329. public static string ByteToHexString(byte[] InBytes)
  330. {
  331. return ByteToHexString(InBytes, (char)0);
  332. }
  333. /// <summary>
  334. /// 字节数据转化成16进制表示的字符串
  335. /// </summary>
  336. /// <param name="InBytes">字节数组</param>
  337. /// <param name="segment">分割符</param>
  338. /// <returns>返回的字符串</returns>
  339. /// <exception cref="NullReferenceException"></exception>
  340. public static string ByteToHexString(byte[] InBytes, char segment)
  341. {
  342. StringBuilder sb = new StringBuilder();
  343. foreach (byte InByte in InBytes)
  344. {
  345. if (segment == 0) sb.Append(string.Format("{0:X2}", InByte));
  346. else sb.Append(string.Format("{0:X2}{1}", InByte, segment));
  347. }
  348. if (segment != 0 && sb.Length > 1 && sb[sb.Length - 1] == segment)
  349. {
  350. sb.Remove(sb.Length - 1, 1);
  351. }
  352. return sb.ToString();
  353. }
  354. /// <summary>
  355. /// 字符串数据转化成16进制表示的字符串
  356. /// </summary>
  357. /// <param name="InString">输入的字符串数据</param>
  358. /// <returns>返回的字符串</returns>
  359. /// <exception cref="NullReferenceException"></exception>
  360. public static string ByteToHexString(string InString)
  361. {
  362. return ByteToHexString(Encoding.Unicode.GetBytes(InString));
  363. }
  364. /// <summary>
  365. /// 将16进制的字符串转化成Byte数据,将检测每2个字符转化,也就是说,中间可以是任意字符
  366. /// </summary>
  367. /// <param name="hex"></param>
  368. /// <returns></returns>
  369. public static byte[] HexStringToBytes(string hex)
  370. {
  371. hex = hex.ToUpper();
  372. List<char> data = new List<char>()
  373. {
  374. '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
  375. };
  376. MemoryStream ms = new MemoryStream();
  377. for (int i = 0; i < hex.Length; i++)
  378. {
  379. if ((i + 1) < hex.Length)
  380. {
  381. if (data.Contains(hex[i]) && data.Contains(hex[i + 1]))
  382. {
  383. // 这是一个合格的字节数据
  384. ms.WriteByte((byte)(data.IndexOf(hex[i]) * 16 + data.IndexOf(hex[i + 1])));
  385. i++;
  386. }
  387. }
  388. }
  389. byte[] result = ms.ToArray();
  390. ms.Dispose();
  391. return result;
  392. }
  393. #endregion
  394. #region Bool[]数组和byte[]相互转化块
  395. /// <summary>
  396. /// 将bool数组转换到byte数组
  397. /// </summary>
  398. /// <param name="array"></param>
  399. /// <returns></returns>
  400. public static byte[] BoolArrayToByte(bool[] array)
  401. {
  402. if (array == null) return null;
  403. int length = array.Length % 8 == 0 ? array.Length / 8 : array.Length / 8 + 1;
  404. byte[] buffer = new byte[length];
  405. for (int i = 0; i < array.Length; i++)
  406. {
  407. int index = i / 8;
  408. int offect = i % 8;
  409. byte temp = 0;
  410. switch (offect)
  411. {
  412. case 0: temp = 0x01; break;
  413. case 1: temp = 0x02; break;
  414. case 2: temp = 0x04; break;
  415. case 3: temp = 0x08; break;
  416. case 4: temp = 0x10; break;
  417. case 5: temp = 0x20; break;
  418. case 6: temp = 0x40; break;
  419. case 7: temp = 0x80; break;
  420. default: break;
  421. }
  422. if (array[i]) buffer[index] += temp;
  423. }
  424. return buffer;
  425. }
  426. /// <summary>
  427. /// 从Byte数组中提取位数组
  428. /// </summary>
  429. /// <param name="InBytes">原先的字节数组</param>
  430. /// <param name="length">想要转换的长度,如果超出自动会缩小到数组最大长度</param>
  431. /// <returns></returns>
  432. public static bool[] ByteToBoolArray(byte[] InBytes, int length)
  433. {
  434. if (InBytes == null) return null;
  435. if (length > InBytes.Length * 8) length = InBytes.Length * 8;
  436. bool[] buffer = new bool[length];
  437. for (int i = 0; i < length; i++)
  438. {
  439. int index = i / 8;
  440. int offect = i % 8;
  441. byte temp = 0;
  442. switch (offect)
  443. {
  444. case 0: temp = 0x01; break;
  445. case 1: temp = 0x02; break;
  446. case 2: temp = 0x04; break;
  447. case 3: temp = 0x08; break;
  448. case 4: temp = 0x10; break;
  449. case 5: temp = 0x20; break;
  450. case 6: temp = 0x40; break;
  451. case 7: temp = 0x80; break;
  452. default: break;
  453. }
  454. if ((InBytes[index] & temp) == temp)
  455. {
  456. buffer[i] = true;
  457. }
  458. }
  459. return buffer;
  460. }
  461. #endregion
  462. #region byte[]数组和short,ushort相互转化
  463. /*******************************************************************************************************
  464. *
  465. * 2018年3月19日 10:57:11
  466. * 感谢:毛毛虫 提供的BUG报告 316664767@qq.com
  467. *
  468. ********************************************************************************************************/
  469. /// <summary>
  470. /// 从byte数组中提取出short数组,并指定是否需要高地位置换
  471. /// </summary>
  472. /// <param name="InBytes"></param>
  473. /// <param name="reverse"></param>
  474. /// <returns></returns>
  475. public static short[] ByteToShortArray( byte[] InBytes, bool reverse )
  476. {
  477. if (InBytes == null) return null;
  478. short[] array = new short[InBytes.Length / 2];
  479. for (int i = 0; i < array.Length; i++)
  480. {
  481. byte[] temp = new byte[2];
  482. if (reverse)
  483. {
  484. temp[0] = InBytes[2 * i + 1];
  485. temp[1] = InBytes[2 * i + 0];
  486. }
  487. else
  488. {
  489. temp[0] = InBytes[2 * i + 0];
  490. temp[1] = InBytes[2 * i + 1];
  491. }
  492. array[i] = BitConverter.ToInt16( temp, 0 );
  493. }
  494. return array;
  495. }
  496. /// <summary>
  497. /// 从byte数组中提取出ushort数组,并指定是否需要高地位置换
  498. /// </summary>
  499. /// <param name="InBytes"></param>
  500. /// <param name="reverse"></param>
  501. /// <returns></returns>
  502. public static ushort[] ByteToUShortArray( byte[] InBytes, bool reverse )
  503. {
  504. if (InBytes == null) return null;
  505. ushort[] array = new ushort[InBytes.Length / 2];
  506. for (int i = 0; i < array.Length; i++)
  507. {
  508. byte[] temp = new byte[2];
  509. if (reverse)
  510. {
  511. temp[0] = InBytes[2 * i + 1];
  512. temp[1] = InBytes[2 * i + 0];
  513. }
  514. else
  515. {
  516. temp[0] = InBytes[2 * i + 0];
  517. temp[1] = InBytes[2 * i + 1];
  518. }
  519. array[i] = BitConverter.ToUInt16( temp, 0 );
  520. }
  521. return array;
  522. }
  523. #endregion
  524. #region 基础框架块
  525. /// <summary>
  526. /// 设置或获取系统框架的版本号
  527. /// </summary>
  528. public static SystemVersion FrameworkVersion { get; set; } = new SystemVersion("1.0.2");
  529. #endregion
  530. #region 深度克隆对象
  531. /// <summary>
  532. /// 使用序列化反序列化深度克隆一个对象
  533. /// </summary>
  534. /// <param name="oringinal"></param>
  535. /// <returns></returns>
  536. /// <exception cref="NullReferenceException"></exception>
  537. public static object DeepClone(object oringinal)
  538. {
  539. using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
  540. {
  541. BinaryFormatter formatter = new BinaryFormatter()
  542. {
  543. Context = new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.StreamingContextStates.Clone)
  544. };
  545. formatter.Serialize(stream, oringinal);
  546. stream.Position = 0;
  547. return formatter.Deserialize(stream);
  548. }
  549. }
  550. #endregion
  551. #region 获取唯一的一串字符串
  552. /// <summary>
  553. /// 获取一串唯一的随机字符串,长度为20,由Guid码和4位数的随机数组成,保证字符串的唯一性
  554. /// </summary>
  555. /// <returns>随机字符串数据</returns>
  556. public static string GetUniqueStringByGuidAndRandom()
  557. {
  558. Random random = new Random();
  559. return Guid.NewGuid().ToString("N") + random.Next(1000, 10000);
  560. }
  561. #endregion
  562. }
  563. }