///////////////////////////////////////////////////////////////////////////////// // 宁波拓通e智造平台 ToTong Next Builder // // https://git.tuotong-tech.com/tnb/tnb.server // ///////////////////////////////////////////////////////////////////////////////// using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using JNPF.Common.Extension; using JNPF.DependencyInjection; namespace System; /// /// 字符串扩展类,来自Abp /// [SuppressSniffer] public static class StringExtensions { /// /// Adds a char to end of given string if it does not ends with the char. /// public static string EnsureEndsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal) { ThrowIf.IsNull(str, nameof(str)); if (str.EndsWith(c.ToString(), comparisonType)) { return str; } return str + c; } /// /// Adds a char to beginning of given string if it does not starts with the char. /// public static string EnsureStartsWith(this string str, char c, StringComparison comparisonType = StringComparison.Ordinal) { ThrowIf.IsNull(str, nameof(str)); if (str.StartsWith(c.ToString(), comparisonType)) { return str; } return c + str; } /// /// Indicates whether this string is null or an System.String.Empty string. /// public static bool IsNullOrEmpty(this string str) { return string.IsNullOrEmpty(str); } /// /// indicates whether this string is null, empty, or consists only of white-space characters. /// public static bool IsNullOrWhiteSpace(this string str) { return string.IsNullOrWhiteSpace(str); } /// /// Gets a substring of a string from beginning of the string. /// /// Thrown if is null /// Thrown if is bigger that string's length public static string Left(this string str, int len) { ThrowIf.IsNull(str, nameof(str)); if (str.Length < len) { throw new ArgumentException("len argument can not be bigger than given string's length!"); } return str.Substring(0, len); } /// /// Converts line endings in the string to . /// public static string NormalizeLineEndings(this string str) { return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine); } /// /// Gets index of nth occurrence of a char in a string. /// /// source string to be searched /// Char to search in /// Count of the occurrence public static int NthIndexOf(this string str, char c, int n) { ThrowIf.IsNull(str, nameof(str)); var count = 0; for (var i = 0; i < str.Length; i++) { if (str[i] != c) { continue; } if ((++count) == n) { return i; } } return -1; } /// /// Removes first occurrence of the given postfixes from end of the given string. /// /// The string. /// one or more postfix. /// Modified string or the same string if it has not any of given postfixes public static string RemovePostFix(this string str, params string[] postFixes) { return str.RemovePostFix(StringComparison.Ordinal, postFixes); } /// /// Removes first occurrence of the given postfixes from end of the given string. /// /// The string. /// String comparison type /// one or more postfix. /// Modified string or the same string if it has not any of given postfixes public static string RemovePostFix(this string str, StringComparison comparisonType, params string[] postFixes) { if (str.IsNullOrEmpty()) { return str; } if (postFixes.IsNullOrEmpty()) { return str; } foreach (var postFix in postFixes) { if (str.EndsWith(postFix, comparisonType)) { return str.Left(str.Length - postFix.Length); } } return str; } /// /// Removes first occurrence of the given prefixes from beginning of the given string. /// /// The string. /// one or more prefix. /// Modified string or the same string if it has not any of given prefixes public static string RemovePreFix(this string str, params string[] preFixes) { return str.RemovePreFix(StringComparison.Ordinal, preFixes); } /// /// Removes first occurrence of the given prefixes from beginning of the given string. /// /// The string. /// String comparison type /// one or more prefix. /// Modified string or the same string if it has not any of given prefixes public static string RemovePreFix(this string str, StringComparison comparisonType, params string[] preFixes) { if (str.IsNullOrEmpty()) { return str; } if (preFixes.IsNullOrEmpty()) { return str; } foreach (var preFix in preFixes) { if (str.StartsWith(preFix, comparisonType)) { return str.Right(str.Length - preFix.Length); } } return str; } public static string ReplaceFirst(this string str, string search, string replace, StringComparison comparisonType = StringComparison.Ordinal) { var pos = str.IndexOf(search, comparisonType); if (pos < 0) { return str; } return str.Substring(0, pos) + replace + str.Substring(pos + search.Length); } /// /// Gets a substring of a string from end of the string. /// /// Thrown if is null /// Thrown if is bigger that string's length public static string Right(this string str, int len) { if (str.Length < len) { throw new ArgumentException("len argument can not be bigger than given string's length!"); } return str.Substring(str.Length - len, len); } /// /// Uses string.Split method to split given string by given separator. /// public static string[] Split(this string str, string separator) { return str.Split(new[] { separator }, StringSplitOptions.None); } /// /// Uses string.Split method to split given string by given separator. /// public static string[] Split(this string str, string separator, StringSplitOptions options) { return str.Split(new[] { separator }, options); } /// /// Uses string.Split method to split given string by . /// public static string[] SplitToLines(this string str) { return str.Split(Environment.NewLine); } /// /// Uses string.Split method to split given string by . /// public static string[] SplitToLines(this string str, StringSplitOptions options) { return str.Split(Environment.NewLine, options); } /// /// Converts PascalCase string to camelCase string. /// /// String to convert /// set true to use current culture. Otherwise, invariant culture will be used. /// set true to if you want to convert 'XYZ' to 'xyz'. /// camelCase of the string public static string ToCamelCase(this string str, bool useCurrentCulture = false, bool handleAbbreviations = false) { if (string.IsNullOrWhiteSpace(str)) { return str; } if (str.Length == 1) { return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant(); } if (handleAbbreviations && IsAllUpperCase(str)) { return useCurrentCulture ? str.ToLower() : str.ToLowerInvariant(); } return (useCurrentCulture ? char.ToLower(str[0]) : char.ToLowerInvariant(str[0])) + str.Substring(1); } /// /// Converts given PascalCase/camelCase string to sentence (by splitting words by space). /// Example: "ThisIsSampleSentence" is converted to "This is a sample sentence". /// /// String to convert. /// set true to use current culture. Otherwise, invariant culture will be used. public static string ToSentenceCase(this string str, bool useCurrentCulture = false) { if (string.IsNullOrWhiteSpace(str)) { return str; } return useCurrentCulture ? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1])) : Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLowerInvariant(m.Value[1])); } /// /// Converts given PascalCase/camelCase string to kebab-case. /// /// String to convert. /// set true to use current culture. Otherwise, invariant culture will be used. public static string ToKebabCase(this string str, bool useCurrentCulture = false) { if (string.IsNullOrWhiteSpace(str)) { return str; } str = str.ToCamelCase(); return useCurrentCulture ? Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLower(m.Value[1])) : Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + "-" + char.ToLowerInvariant(m.Value[1])); } /// /// Converts given PascalCase/camelCase string to snake case. /// Example: "ThisIsSampleSentence" is converted to "this_is_a_sample_sentence". /// https://github.com/npgsql/npgsql/blob/dev/src/Npgsql/NameTranslation/NpgsqlSnakeCaseNameTranslator.cs#L51 /// /// String to convert. /// public static string ToSnakeCase(this string str) { if (string.IsNullOrWhiteSpace(str)) { return str; } var builder = new StringBuilder(str.Length + Math.Min(2, str.Length / 5)); var previousCategory = default(UnicodeCategory?); for (var currentIndex = 0; currentIndex < str.Length; currentIndex++) { var currentChar = str[currentIndex]; if (currentChar == '_') { builder.Append('_'); previousCategory = null; continue; } var currentCategory = char.GetUnicodeCategory(currentChar); switch (currentCategory) { case UnicodeCategory.UppercaseLetter: case UnicodeCategory.TitlecaseLetter: if (previousCategory == UnicodeCategory.SpaceSeparator || previousCategory == UnicodeCategory.LowercaseLetter || previousCategory != UnicodeCategory.DecimalDigitNumber && previousCategory != null && currentIndex > 0 && currentIndex + 1 < str.Length && char.IsLower(str[currentIndex + 1])) { builder.Append('_'); } currentChar = char.ToLower(currentChar); break; case UnicodeCategory.LowercaseLetter: case UnicodeCategory.DecimalDigitNumber: if (previousCategory == UnicodeCategory.SpaceSeparator) { builder.Append('_'); } break; default: if (previousCategory != null) { previousCategory = UnicodeCategory.SpaceSeparator; } continue; } builder.Append(currentChar); previousCategory = currentCategory; } return builder.ToString(); } /// /// Converts string to enum value. /// /// Type of enum /// String value to convert /// Returns enum object public static T ToEnum(this string value) where T : struct { ThrowIf.IsNull(value, nameof(value)); return (T)Enum.Parse(typeof(T), value); } /// /// Converts string to enum value. /// /// Type of enum /// String value to convert /// Ignore case /// Returns enum object public static T ToEnum(this string value, bool ignoreCase) where T : struct { ThrowIf.IsNull(value, nameof(value)); return (T)Enum.Parse(typeof(T), value, ignoreCase); } public static string ToMd5(this string str) { using (var md5 = MD5.Create()) { var inputBytes = Encoding.UTF8.GetBytes(str); var hashBytes = md5.ComputeHash(inputBytes); var sb = new StringBuilder(); foreach (var hashByte in hashBytes) { sb.Append(hashByte.ToString("X2")); } return sb.ToString(); } } /// /// Converts camelCase string to PascalCase string. /// /// String to convert /// set true to use current culture. Otherwise, invariant culture will be used. /// PascalCase of the string public static string ToPascalCase(this string str, bool useCurrentCulture = false) { if (string.IsNullOrWhiteSpace(str)) { return str; } if (str.Length == 1) { return useCurrentCulture ? str.ToUpper() : str.ToUpperInvariant(); } return (useCurrentCulture ? char.ToUpper(str[0]) : char.ToUpperInvariant(str[0])) + str.Substring(1); } /// /// Gets a substring of a string from beginning of the string if it exceeds maximum length. /// public static string Truncate(this string str, int maxLength) { if (str.Length <= maxLength) { return str; } return str.Left(maxLength); } /// /// Gets a substring of a string from Ending of the string if it exceeds maximum length. /// public static string TruncateFromBeginning(this string str, int maxLength) { if (str.Length <= maxLength) { return str; } return str.Right(maxLength); } /// /// Gets a substring of a string from beginning of the string if it exceeds maximum length. /// It adds a "..." postfix to end of the string if it's truncated. /// Returning string can not be longer than maxLength. /// /// Thrown if is null public static string TruncateWithPostfix(this string str, int maxLength) { return TruncateWithPostfix(str, maxLength, "..."); } /// /// Gets a substring of a string from beginning of the string if it exceeds maximum length. /// It adds given to end of the string if it's truncated. /// Returning string can not be longer than maxLength. /// /// Thrown if is null public static string TruncateWithPostfix(this string str, int maxLength, string postfix) { if (str == string.Empty || maxLength == 0) { return string.Empty; } if (str.Length <= maxLength) { return str; } if (maxLength <= postfix.Length) { return postfix.Left(maxLength); } return str.Left(maxLength - postfix.Length) + postfix; } /// /// Converts given string to a byte array using encoding. /// public static byte[] GetBytes(this string str) { return str.GetBytes(Encoding.UTF8); } /// /// Converts given string to a byte array using the given /// public static byte[] GetBytes([NotNull] this string str, [NotNull] Encoding encoding) { ThrowIf.IsNull(str, nameof(str)); ThrowIf.IsNull(encoding, nameof(encoding)); return encoding.GetBytes(str); } private static bool IsAllUpperCase(string input) { for (int i = 0; i < input.Length; i++) { if (Char.IsLetter(input[i]) && !Char.IsUpper(input[i])) { return false; } } return true; } /// /// Converts snake_case string to PascalCase string. /// /// String to convert /// set true to use current culture. Otherwise, invariant culture will be used. /// PascalCase of the string public static string SnakeToPascalCase(this string str, bool useCurrentCulture = false) { var sArr = str.Split(new char[] { '-', '_' }).Select(a => a.ToPascalCase(useCurrentCulture)); return string.Join("", sArr); } /// /// Converts snake_case string to PascalCase string. /// /// String to convert /// set true to use current culture. Otherwise, invariant culture will be used. /// PascalCase of the string public static string SnakeToCamelCase(this string str, bool useCurrentCulture = false) { return SnakeToPascalCase(str, useCurrentCulture).ToCamelCase(); } }