using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; [UnityEngine.Scripting.Preserve] public static class StringExtension { /// /// 快速比较两个字符串内容是否一致 /// /// 当前字符串 /// 对比的目标字符串 /// /// 当前对象为空 public static bool EqualsFast(this string self, string target) { if (self == null) { return target == null; } if (target == null) { return false; } if (self.Length != target.Length) { return false; } int ap = self.Length - 1; int bp = target.Length - 1; while (ap >= 0 && bp >= 0 && self[ap] == target[bp]) { ap--; bp--; } return (bp < 0); } /// /// 判断字符串是否以目标字符串结尾 /// /// /// 目标字符串 /// public static bool EndsWithFast(this string self, string target) { int ap = self.Length - 1; int bp = target.Length - 1; while (ap >= 0 && bp >= 0 && self[ap] == target[bp]) { ap--; bp--; } return (bp < 0); } /// /// 判断字符串是否以目标字符串开始 /// /// /// 目标字符串 /// public static bool StartsWithFast(this string self, string target) { int aLen = self.Length; int bLen = target.Length; int ap = 0; int bp = 0; while (ap < aLen && bp < bLen && self[ap] == target[bp]) { ap++; bp++; } return (bp == bLen); } /// /// 字符串转字符数组 /// /// /// public static IEnumerable ToBytes(this string self) { byte[] byteArray = Encoding.Default.GetBytes(self); return byteArray; } /// /// 字符串转字符数组 /// /// /// public static byte[] ToByteArray(this string self) { byte[] byteArray = Encoding.Default.GetBytes(self); return byteArray; } /// /// 字符串转UTF8字符数组 /// /// /// public static byte[] ToUtf8(this string self) { byte[] byteArray = Encoding.UTF8.GetBytes(self); return byteArray; } /// /// 16进制字符串转字节数组 /// /// 字符串 /// /// 字符串字符数不是偶数引发异常 public static byte[] HexToBytes(this string hexString) { if (hexString.Length % 2 != 0) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString)); } var hexAsBytes = new byte[hexString.Length / 2]; for (int index = 0; index < hexAsBytes.Length; index++) { string byteValue = ""; byteValue += hexString[index * 2]; byteValue += hexString[index * 2 + 1]; hexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture); } return hexAsBytes; } /// /// 指定的字符串是 null、空还是仅由空白字符组成。 /// /// /// public static bool IsNullOrWhiteSpace(this string self) { const string nullString = "null"; return self.EqualsFast(nullString) || string.IsNullOrWhiteSpace(self); } /// /// 指定的字符串是 null 还是 Empty 字符串。 /// /// /// public static bool IsNullOrEmpty(this string self) { return string.IsNullOrEmpty(self); } /// /// 指定的字符串[不]是 null、空还是仅由空白字符组成。 /// /// /// public static bool IsNotNullOrWhiteSpace(this string self) { return !self.IsNullOrWhiteSpace(); } /// /// 指定的字符串[不]是 null 还是 Empty 字符串。 /// /// /// public static bool IsNotNullOrEmpty(this string self) { return !self.IsNullOrEmpty(); } /// /// 格式化 /// /// /// /// public static string Format(this string text, params object[] args) { return string.Format(text, args); } /// /// 转换为标题格式。 /// public static string ToTitleCase(this string str) { return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower()); } /// /// 判断字符串是否为空。 /// public static bool IsEmpty(this string str) { return string.IsNullOrEmpty(str); } /// /// 返回当前字符串,若为空则返回备用值。 /// public static string Or(this string str, string otherwise) { return !string.IsNullOrEmpty(str) ? str : otherwise; } /// /// 将[\n、\t、\r、空格]替换为空,并返回 /// /// 原始字符串 /// public static string TrimEmpty(this string self) { self = self.Replace("\n", string.Empty).Replace(" ", string.Empty).Replace("\t", string.Empty).Replace("\r", string.Empty); return self; } /// /// 匹配中文正则表达式 /// private static readonly Regex CnReg = new Regex(@"[\u4e00-\u9fa5]"); /// /// 替换中文为空字符串 /// /// 原始字符串 /// public static string TrimZhCn(this string self) { self = CnReg.Replace(self, string.Empty); return self; } /// /// 替换起止字符之间的片段。 /// public static string ReplacePart(this string str, char start, char end, string replace) { int chStart = str.IndexOf(start); int chEnd = str.IndexOf(end); string old = str.Substring(chStart, chEnd - chStart + 1); return str.Replace(old, replace); } /// /// 替换指定包裹标记中的内容。 /// public static string RegexReplaceTag(this string str, char start, char end, string tag, string replace) { Regex regex = new Regex($@"\{start}({tag})\{end}"); if (regex.Match(str).Success) { return regex.Replace(str, replace); } return str; } /// /// 读取起止字符之间的内容。 /// public static bool RegexGet(this string str, char start, char end, out string result) { string escapedStart = Regex.Escape(start.ToString()); string escapedEnd = Regex.Escape(end.ToString()); string pattern = $"{escapedStart}(.*?){escapedEnd}"; Match match = Regex.Match(str, pattern); if (match.Success) { result = match.Groups[1].Value; return true; } result = string.Empty; return false; } /// /// 读取所有起止字符之间的内容。 /// public static bool RegexGetMany(this string str, char start, char end, out string[] results) { string escapedStart = Regex.Escape(start.ToString()); string escapedEnd = Regex.Escape(end.ToString()); string pattern = $"{escapedStart}(.*?){escapedEnd}"; MatchCollection matches = Regex.Matches(str, pattern); if (matches.Count > 0) { var matchList = new List(); foreach (Match match in matches) { matchList.Add(match.Groups[1].Value); } results = matchList.ToArray(); return true; } results = Array.Empty(); return false; } /// /// 以单词为边界替换内容。 /// public static string RegexReplace(this string str, string word, string replace) { string escapedWord = Regex.Escape(word); string pattern = $@"\b{escapedWord}\b"; return Regex.Replace(str, pattern, replace); } public static int[] SplitToIntArray(this string str, char sep = '+') { if (string.IsNullOrEmpty(str)) return Array.Empty(); var arr = str.Split(sep); int[] ret = new int[arr.Length]; for (int i = 0; i < arr.Length; ++i) { if (int.TryParse(arr[i], out var t)) ret[i] = t; } return ret; } public static int[][] SplitTo2IntArray(this string str, char sep1 = ';', char sep2 = '+') { if (string.IsNullOrEmpty(str)) return Array.Empty(); var arr = str.Split(sep1); if (arr.Length <= 0) return Array.Empty(); int[][] ret = new int[arr.Length][]; for (int i = 0; i < arr.Length; ++i) ret[i] = arr[i].SplitToIntArray(sep2); return ret; } /// /// 根据字符串创建目录,递归 /// public static void CreateAsDirectory(this string path, bool isFile = false) { if (isFile) { path = Path.GetDirectoryName(path); } if (!Directory.Exists(path)) { CreateAsDirectory(path, true); Directory.CreateDirectory(path); } } /// /// 从指定字符串中的指定位置处开始读取一行。 /// /// 指定的字符串。 /// 从指定位置处开始读取一行,读取后将返回下一行开始的位置。 /// 读取的一行字符串。 public static string ReadLine(this string rawString, ref int position) { if (position < 0) { return null; } int length = rawString.Length; int offset = position; while (offset < length) { char ch = rawString[offset]; switch (ch) { case '\r': case '\n': if (offset > position) { string line = rawString.Substring(position, offset - position); position = offset + 1; if ((ch == '\r') && (position < length) && (rawString[position] == '\n')) { position++; } return line; } offset++; position++; break; default: offset++; break; } } if (offset > position) { string line = rawString.Substring(position, offset - position); position = offset; return line; } return null; } }