StringExtensions.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. using Ips.Library.Basic;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Security.Cryptography;
  6. using System.Text;
  7. using System.Text.Encodings.Web;
  8. using System.Text.Json.Serialization;
  9. using System.Text.Json;
  10. using System.Text.RegularExpressions;
  11. using System.Text.Unicode;
  12. using Newtonsoft.Json;
  13. using System.Net;
  14. //namespace Ips.Library.Basic
  15. //{
  16. public static class StringExtensions
  17. {
  18. public static string[] ToStrArray(this string @this)
  19. {
  20. return new string[1]
  21. {
  22. @this
  23. };
  24. }
  25. public static List<string> ToStrList(this string @this)
  26. {
  27. return new List<string>
  28. {
  29. @this
  30. };
  31. }
  32. /// <summary>
  33. /// 使用Newtonsoft Json将string转换为对象
  34. /// </summary>
  35. /// <param name="this"></param>
  36. /// <returns></returns>
  37. public static T ToObj<T>(this string @this)
  38. {
  39. JsonSerializerSettings jsonSettings = new JsonSerializerSettings
  40. {
  41. DateFormatString = "yyyy-MM-dd HH:mm:ss",
  42. };
  43. return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(@this, jsonSettings);
  44. }
  45. /// <summary>
  46. /// 为url字符串添加后缀
  47. /// </summary>
  48. /// <param name="this"></param>
  49. /// <param name="suffix"></param>
  50. /// <returns></returns>
  51. public static string AppendUrlSuffix(this string @this, string suffix)
  52. {
  53. if (suffix.StartsWith("/"))
  54. suffix = suffix.Substring(1);
  55. if (@this.EndsWith("/"))
  56. return $"{@this}{suffix}";
  57. else
  58. return $"{@this}/{suffix}";
  59. }
  60. /// <summary>
  61. /// 获取url中的端口
  62. /// </summary>
  63. /// <param name="this"></param>
  64. /// <returns></returns>
  65. public static int GetUrlPort(this string @this)
  66. {
  67. try
  68. {
  69. bool isHttps = @this.ToLower().StartsWith("https");
  70. var newStr = @this.ToLower().Replace("https://", "").Replace("http://", "");
  71. var idx1 = newStr.IndexOf(":");
  72. if (idx1 < 0)
  73. {
  74. if (isHttps)
  75. return 443;
  76. else
  77. return 80;
  78. }
  79. var idx2 = newStr.IndexOf("/");
  80. var str = newStr.Substring(idx1 + 1, idx2 - idx1 - 1);
  81. return Convert.ToInt32(str);
  82. }
  83. catch
  84. {
  85. return 0;
  86. }
  87. }
  88. public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal)
  89. {
  90. if (str.EndsWith(c.ToString(), comparisonType))
  91. {
  92. return str;
  93. }
  94. return str + c;
  95. }
  96. public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal)
  97. {
  98. if (str.StartsWith(c.ToString(), comparisonType))
  99. {
  100. return str;
  101. }
  102. return c + str;
  103. }
  104. public static bool IsNullOrEmpty(this string @this)
  105. {
  106. return String.IsNullOrEmpty(@this);
  107. }
  108. public static bool IsNotNullOrEmpty(this string @this)
  109. {
  110. return !String.IsNullOrEmpty(@this);
  111. }
  112. public static bool IsNullOrWhitespace(this string @this)
  113. {
  114. return String.IsNullOrWhiteSpace(@this);
  115. }
  116. public static bool IsNotNullOrWhitespace(this string @this)
  117. {
  118. return !String.IsNullOrWhiteSpace(@this);
  119. }
  120. public static string IfNullOrEmpty(this string @this, string defaultVal)
  121. {
  122. return String.IsNullOrEmpty(@this) ? defaultVal : @this;
  123. }
  124. public static string IfNullOrWhitespace(this string @this, string defaultVal)
  125. {
  126. return String.IsNullOrWhiteSpace(@this) ? defaultVal : @this;
  127. }
  128. public static string ClearWhitespace(this string @this)
  129. {
  130. if (String.IsNullOrWhiteSpace(@this)) return String.Empty;
  131. return @this.Replace(" ", String.Empty);
  132. }
  133. public static string Left(this string @this, int length)
  134. {
  135. if (String.IsNullOrEmpty(@this)) return String.Empty;
  136. return @this.Length < length ? @this : @this.Substring(0, length);
  137. }
  138. public static string Rigth(this string @this, int length)
  139. {
  140. if (String.IsNullOrEmpty(@this)) return String.Empty;
  141. return @this.Length < length ? @this : @this.Substring(@this.Length - length);
  142. }
  143. public static string TrimToMaxLength(this string @this, int maxLength, string suffix = "")
  144. {
  145. return ((@this == null || @this.Length <= maxLength) ? @this : String.Concat(@this.Substring(0, maxLength), suffix));
  146. }
  147. public static T To<T>(this string @this)
  148. {
  149. return To(@this, default(T));
  150. }
  151. public static T To<T>(this string @this, T defaultValue)
  152. {
  153. if (String.IsNullOrWhiteSpace(@this))
  154. return defaultValue;
  155. T retVal = defaultValue;
  156. try
  157. {
  158. //获取要转换的目标类型
  159. Type targetType = typeof(T);
  160. //对 Guid 类型的值进行单独处理
  161. if (targetType == typeof(Guid))
  162. retVal = (T)((object)(new Guid(@this)));
  163. //对 Enum 类型的值进行单独处理
  164. else if (targetType.BaseType == typeof(Enum))
  165. retVal = (T)Enum.Parse(targetType, @this);
  166. else
  167. retVal = (T)Convert.ChangeType(@this, targetType);
  168. }
  169. catch { }
  170. return retVal;
  171. }
  172. public static string NormalizeLineEndings(this string str)
  173. {
  174. return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine);
  175. }
  176. public static int NthIndexOf(this string str, char c, int n)
  177. {
  178. var count = 0;
  179. for (var i = 0; i < str.Length; i++)
  180. {
  181. if (str[i] != c)
  182. {
  183. continue;
  184. }
  185. if ((++count) == n)
  186. {
  187. return i;
  188. }
  189. }
  190. return -1;
  191. }
  192. public static string RemovePostFix(this string str, params string[] postFixes)
  193. {
  194. return str.RemovePostFix(StringComparison.Ordinal, postFixes);
  195. }
  196. public static string RemovePostFix(this string str, StringComparison comparisonType, params string[] postFixes)
  197. {
  198. if (str.IsNullOrEmpty())
  199. {
  200. return str;
  201. }
  202. if (postFixes.IsNullOrEmpty())
  203. {
  204. return str;
  205. }
  206. foreach (var postFix in postFixes)
  207. {
  208. if (str.EndsWith(postFix, comparisonType))
  209. {
  210. return str.Left(str.Length - postFix.Length);
  211. }
  212. }
  213. return str;
  214. }
  215. public static string RemovePreFix(this string str, params string[] preFixes)
  216. {
  217. return str.RemovePreFix(StringComparison.Ordinal, preFixes);
  218. }
  219. public static string RemovePreFix(this string str, StringComparison comparisonType, params string[] preFixes)
  220. {
  221. if (str.IsNullOrEmpty())
  222. {
  223. return str;
  224. }
  225. if (preFixes.IsNullOrEmpty())
  226. {
  227. return str;
  228. }
  229. foreach (var preFix in preFixes)
  230. {
  231. if (str.StartsWith(preFix, comparisonType))
  232. {
  233. return str.Right(str.Length - preFix.Length);
  234. }
  235. }
  236. return str;
  237. }
  238. public static string ReplaceFirst(this string str, string search, string replace, StringComparison comparisonType = StringComparison.Ordinal)
  239. {
  240. var pos = str.IndexOf(search, comparisonType);
  241. if (pos < 0)
  242. {
  243. return str;
  244. }
  245. return str.Substring(0, pos) + replace + str.Substring(pos + search.Length);
  246. }
  247. public static string Right(this string str, int len)
  248. {
  249. if (str.Length < len)
  250. {
  251. throw new ArgumentException("len argument can not be bigger than given string's length!");
  252. }
  253. return str.Substring(str.Length - len, len);
  254. }
  255. public static string[] Split(this string str, string separator)
  256. {
  257. return str.Split(new[] { separator }, StringSplitOptions.None);
  258. }
  259. public static string[] Split(this string str, string separator, StringSplitOptions options)
  260. {
  261. return str.Split(new[] { separator }, options);
  262. }
  263. public static string[] SplitToLines(this string str)
  264. {
  265. return str.Split(Environment.NewLine);
  266. }
  267. public static string[] SplitToLines(this string str, StringSplitOptions options)
  268. {
  269. return str.Split(Environment.NewLine, options);
  270. }
  271. public static string ToCamelCase(this string str, bool useCurrentCulture = false, bool handleAbbreviations = false)
  272. {
  273. if (string.IsNullOrWhiteSpace(str))
  274. {
  275. return str;
  276. }
  277. if (str.Length == 1)
  278. {
  279. return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant();
  280. }
  281. if (handleAbbreviations && IsAllUpperCase(str))
  282. {
  283. return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant();
  284. }
  285. return (useCurrentCulture ? char.ToLower(str[0]) : char.ToLowerInvariant(str[0])) + str.Substring(1);
  286. }
  287. public static string ToSentenceCase(this string str, bool useCurrentCulture = false)
  288. {
  289. if (string.IsNullOrWhiteSpace(str))
  290. {
  291. return str;
  292. }
  293. return useCurrentCulture
  294. ? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]))
  295. : Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLowerInvariant(m.Value[1]));
  296. }
  297. public static string ToKebabCase(this string str, bool useCurrentCulture = false)
  298. {
  299. if (string.IsNullOrWhiteSpace(str))
  300. {
  301. return str;
  302. }
  303. str = str.ToCamelCase();
  304. return useCurrentCulture
  305. ? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLower(m.Value[1]))
  306. : Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLowerInvariant(m.Value[1]));
  307. }
  308. public static string ToSnakeCase(this string str)
  309. {
  310. if (string.IsNullOrWhiteSpace(str))
  311. {
  312. return str;
  313. }
  314. var builder = new StringBuilder(str.Length + Math.Min(2, str.Length / 5));
  315. var previousCategory = default(UnicodeCategory?);
  316. for (var currentIndex = 0; currentIndex < str.Length; currentIndex++)
  317. {
  318. var currentChar = str[currentIndex];
  319. if (currentChar == '_')
  320. {
  321. builder.Append('_');
  322. previousCategory = null;
  323. continue;
  324. }
  325. var currentCategory = char.GetUnicodeCategory(currentChar);
  326. switch (currentCategory)
  327. {
  328. case UnicodeCategory.UppercaseLetter:
  329. case UnicodeCategory.TitlecaseLetter:
  330. if (previousCategory == UnicodeCategory.SpaceSeparator ||
  331. previousCategory == UnicodeCategory.LowercaseLetter ||
  332. previousCategory != UnicodeCategory.DecimalDigitNumber &&
  333. previousCategory != null &&
  334. currentIndex > 0 &&
  335. currentIndex + 1 < str.Length &&
  336. char.IsLower(str[currentIndex + 1]))
  337. {
  338. builder.Append('_');
  339. }
  340. currentChar = char.ToLower(currentChar);
  341. break;
  342. case UnicodeCategory.LowercaseLetter:
  343. case UnicodeCategory.DecimalDigitNumber:
  344. if (previousCategory == UnicodeCategory.SpaceSeparator)
  345. {
  346. builder.Append('_');
  347. }
  348. break;
  349. default:
  350. if (previousCategory != null)
  351. {
  352. previousCategory = UnicodeCategory.SpaceSeparator;
  353. }
  354. continue;
  355. }
  356. builder.Append(currentChar);
  357. previousCategory = currentCategory;
  358. }
  359. return builder.ToString();
  360. }
  361. public static T ToEnum<T>(this string value)
  362. where T : struct
  363. {
  364. return (T)Enum.Parse(typeof(T), value);
  365. }
  366. public static T ToEnum<T>(this string value, bool ignoreCase)
  367. where T : struct
  368. {
  369. return (T)Enum.Parse(typeof(T), value, ignoreCase);
  370. }
  371. public static string ToMd5(this string str)
  372. {
  373. using (var md5 = MD5.Create())
  374. {
  375. var inputBytes = Encoding.UTF8.GetBytes(str);
  376. var hashBytes = md5.ComputeHash(inputBytes);
  377. var sb = new StringBuilder();
  378. foreach (var hashByte in hashBytes)
  379. {
  380. sb.Append(hashByte.ToString("X2"));
  381. }
  382. return sb.ToString();
  383. }
  384. }
  385. public static string ToPascalCase(this string str, bool useCurrentCulture = false)
  386. {
  387. if (string.IsNullOrWhiteSpace(str))
  388. {
  389. return str;
  390. }
  391. if (str.Length == 1)
  392. {
  393. return useCurrentCulture ? str.ToUpper() : str.ToUpperInvariant();
  394. }
  395. return (useCurrentCulture ? char.ToUpper(str[0]) : char.ToUpperInvariant(str[0])) + str.Substring(1);
  396. }
  397. public static string Truncate(this string str, int maxLength)
  398. {
  399. if (str == null)
  400. {
  401. return null;
  402. }
  403. if (str.Length <= maxLength)
  404. {
  405. return str;
  406. }
  407. return str.Left(maxLength);
  408. }
  409. public static string TruncateFromBeginning(this string str, int maxLength)
  410. {
  411. if (str == null)
  412. {
  413. return null;
  414. }
  415. if (str.Length <= maxLength)
  416. {
  417. return str;
  418. }
  419. return str.Right(maxLength);
  420. }
  421. public static string TruncateWithPostfix(this string str, int maxLength)
  422. {
  423. return TruncateWithPostfix(str, maxLength, "...");
  424. }
  425. public static string TruncateWithPostfix(this string str, int maxLength, string postfix)
  426. {
  427. if (str == null)
  428. {
  429. return null;
  430. }
  431. if (str == string.Empty || maxLength == 0)
  432. {
  433. return string.Empty;
  434. }
  435. if (str.Length <= maxLength)
  436. {
  437. return str;
  438. }
  439. if (maxLength <= postfix.Length)
  440. {
  441. return postfix.Left(maxLength);
  442. }
  443. return str.Left(maxLength - postfix.Length) + postfix;
  444. }
  445. public static byte[] GetBytes(this string str)
  446. {
  447. return str.GetBytes(Encoding.UTF8);
  448. }
  449. public static byte[] GetBytes(this string str, Encoding encoding)
  450. {
  451. return encoding.GetBytes(str);
  452. }
  453. private static bool IsAllUpperCase(string input)
  454. {
  455. for (int i = 0; i < input.Length; i++)
  456. {
  457. if (Char.IsLetter(input[i]) && !Char.IsUpper(input[i]))
  458. {
  459. return false;
  460. }
  461. }
  462. return true;
  463. }
  464. public static byte[] ToBytes(this string input, int byteCount = 0, Encoding encoding = null)
  465. {
  466. encoding = encoding ?? Encoding.UTF8;
  467. input = input ?? "";
  468. var strBuffer = encoding.GetBytes(input);
  469. if (byteCount == 0) return strBuffer;
  470. var buffer = new byte[byteCount];
  471. Array.Copy(strBuffer, 0, buffer, 0, Math.Min(strBuffer.Length, buffer.Length));
  472. return buffer;
  473. }
  474. public static IPAddress ToIpAddress(this string strIP)
  475. {
  476. return IPAddress.Parse(strIP);
  477. }
  478. /// <summary>
  479. /// 字符串是否包含字符集合中的某个元素
  480. /// </summary>
  481. /// <param name="str"></param>
  482. /// <param name="values">字符串数组</param>
  483. /// <returns></returns>
  484. public static bool ContainsOne(this string str, IEnumerable<string> values)
  485. {
  486. if (str == null) return false;
  487. foreach (var item in values)
  488. {
  489. if (str.Contains(item)) return true;
  490. }
  491. return false;
  492. }
  493. /// <summary>
  494. /// 字符串是否包含字符集合中的所有元素
  495. /// </summary>
  496. /// <param name="str"></param>
  497. /// <param name="values">字符串数组</param>
  498. /// <returns></returns>
  499. public static bool ContainsAll(this string str, IEnumerable<string> values)
  500. {
  501. if (str == null) return false;
  502. foreach (var item in values)
  503. {
  504. if (!str.Contains(item)) return false;
  505. }
  506. return true;
  507. }
  508. /// <summary>
  509. /// 判断字符串是否为null或空白字符
  510. /// </summary>
  511. /// <param name="s"></param>
  512. /// <returns></returns>
  513. public static bool IsNull(this string s)
  514. {
  515. return string.IsNullOrWhiteSpace(s);
  516. }
  517. /// <summary>
  518. /// 判断字符串是否不为null或空白字符
  519. /// </summary>
  520. /// <param name="s"></param>
  521. /// <returns></returns>
  522. public static bool NotNull(this string s)
  523. {
  524. return !string.IsNullOrWhiteSpace(s);
  525. }
  526. }
  527. //}