/// <summary> /// Проверяет, является ли данная строка корректным адресом электронной почты /// </summary> /// <remarks>Осторожно: регекспы</remarks> /// <param name="Input"></param> /// <returns>Если true - является</returns> public static bool IsValidEmail(String Input) { if (Input.IsStringNullEmptyWhiteSpace() == true) { return false; } return Regex.IsMatch(Input, @"^[-a-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?\.)*" + "(?:aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|[a-z][a-z])$", RegexOptions.IgnoreCase | RegexOptions.Compiled); }
/// <summary> /// Удаляет расширение из имени файла, если находит точку и перед ней есть какие-нибудь символы /// </summary> /// <param name="Filename">Имя файла</param> /// <returns>Входная строка без расширения имени файла</returns> public static String DeleteExtension(String Filename) { if (Filename.IsStringNullEmptyWhiteSpace() == true) { return Filename; } int index_of_dot = Filename.LastIndexOf('.'); if (index_of_dot > 0) { return Filename.Remove(index_of_dot); } else { return Filename; } }
/// <summary> /// Проверяет, может ли указанная строка быть успешно преобразована в тип GUID, являющийся 128-битным числом. /// </summary> /// <remarks>Осторожно: регекспы</remarks> /// <param name="Input">Входная строка, которую надо проверить на совместимость с GUID</param> /// <returns></returns> public static Boolean IsValidGuid(String Input) { if (Input.IsStringNullEmptyWhiteSpace() == true) { return false; } return Regex.Match(Input, @"^ (?:\{)? (?<GUID> [0-9a-f]{8} \- [0-9a-f]{4} \- [0-9a-f]{4} \- [0-9a-f]{4} \- [0-9a-f]{12} ) (?:\})? $", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled). Success; //.NET 4 below //Guid temp; //return Guid.TryParse(Input, out temp); }
/// <summary> /// Возвращает подстроку из входной строки, которая отчитывается от указанной позиции и до указанного вхожденя указанного токена. /// </summary> /// <param name="Input"></param> /// <param name="Token">Номер вхождения указанного токена, начиная с 1</param> /// <param name="Number"></param> /// <param name="StartPosition"></param> /// <param name="ComparisonType"></param> /// <returns></returns> public static String GetSubstringToTokenWithSpecifiedNumber(String Input, String Token, Byte Number, Int32 StartPosition, StringComparison ComparisonType) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (Token.IsStringNullOrEmpty() == true) { throw new ArgumentException("Токен не может быть NULL или пустой строкой", "Token"); } if (Enum.IsDefined(ComparisonType.GetType(), ComparisonType) == false) { throw new InvalidEnumArgumentException("ComparisonType", (Int32)ComparisonType, ComparisonType.GetType()); } if (String.Compare(Input, Token, ComparisonType) == 0) { throw new ArgumentException("Входная строка не может быть равна токену"); } if (Input.Contains(Token, ComparisonType) == false) { return Input; } if (Number == 0) { throw new ArgumentOutOfRangeException("Number", "Номер вхождения указанного токена не может быть нулевой"); } if (StartPosition < 0) { throw new ArgumentOutOfRangeException("StartPosition", StartPosition, "Начальная позиция не может быть меньше 0"); } String sub = Input.Substring(StartPosition); Int32 nums_of_occureses = StringTools.StringAnalyzers.GetNumberOfOccurencesInString(sub, Token, ComparisonType); if (Number > nums_of_occureses) { throw new ArgumentOutOfRangeException("Number", "Указанная бозиция больше, чем количество вхождений токена в части строки"); } List<int> positions = StringTools.StringAnalyzers.GetPositionsOfTokenInString(sub, Token, ComparisonType); Int32 desired_position = positions[Number - 1]; return sub.Substring(0, desired_position); }
/// <summary> /// Возвращает подстроку из входной строки, которая отчитывается от начала или от конца и до указанного вхожденя указанного токена. /// </summary> /// <param name="Input"></param> /// <param name="Token"></param> /// <param name="Number">Номер вхождения указанного токена, начиная с 1</param> /// <param name="Dir"></param> /// <param name="ComparisonType"></param> /// <returns></returns> public static String GetSubstringToTokenWithSpecifiedNumber(String Input, String Token, Byte Number, StringTools.Direction Dir, StringComparison ComparisonType) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (Token.IsStringNullOrEmpty() == true) { throw new ArgumentException("Токен не может быть NULL или пустой строкой", "Token"); } if (Enum.IsDefined(ComparisonType.GetType(), ComparisonType) == false) { throw new InvalidEnumArgumentException("ComparisonType", (Int32)ComparisonType, ComparisonType.GetType()); } if (String.Compare(Input, Token, ComparisonType) == 0) { throw new ArgumentException("Входная строка не может быть равна токену"); } if (Input.Contains(Token, ComparisonType) == false) { return Input; } if (Number == 0) { throw new ArgumentOutOfRangeException("Number", "Номер вхождения указанного токена не может быть нулевой"); } Int32 nums_of_occureses = StringTools.StringAnalyzers.GetNumberOfOccurencesInString(Input, Token, ComparisonType); if (Number > nums_of_occureses) { throw new ArgumentOutOfRangeException("Number", Number, "Указанная позиция больше, чем количество вхождений токена в строке"); } List<int> positions = StringTools.StringAnalyzers.GetPositionsOfTokenInString(Input, Token, ComparisonType); Int32 token_length = Token.Length; Int32 desired_position; switch (Dir) { case StringTools.Direction.FromStartToEnd: desired_position = positions[Number - 1]; return Input.Substring(0, desired_position); case StringTools.Direction.FromEndToStart: desired_position = positions[positions.Count - Number]; return Input.Substring(desired_position + token_length); default: throw new InvalidEnumArgumentException("Dir", (Int32)Dir, Dir.GetType()); } }
/// <summary> /// Возвращает часть указанной входной строки, которая размещена от начала или от конца и до первого указанного токена /// </summary> /// <param name="Input">Входящая строка, из которой надо извлечь подстроку</param> /// <param name="Token">Токен, который определяет конец подстроки</param> /// <param name="LeaveToken">Если "true" - ближайший токен будет оставлен. Если "false" - он тоже будет удалён.</param> /// <param name="Dir">Направление, с которого будет возвращена подстрока: из начала или из конца</param> /// <param name="CompareOptions">Опции сравнения строк между собой</param> /// <returns></returns> public static string GetSubstringToToken(String Input, String Token, Boolean LeaveToken, StringTools.Direction Dir, StringComparison CompareOptions) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (Token.IsStringNullOrEmpty() == true) { throw new ArgumentException("Токен не может быть NULL или пустой строкой", "Token"); } if (String.Compare(Input, Token, CompareOptions) == 0) { throw new ArgumentException("Входная строка не может быть равна токену"); } if (Input.Contains(Token, CompareOptions) == false) { return Input; } Int32 input_length = Input.Length; String temp; switch (Dir) { case StringTools.Direction.FromStartToEnd: Int32 index_of_first_token = Input.IndexOf(Token, CompareOptions); temp = Input.Substring(0, index_of_first_token); if (LeaveToken == false) { return temp; } else { return temp + Token; } case StringTools.Direction.FromEndToStart: Int32 token_length = Token.Length; Int32 index_of_last_token = Input.LastIndexOf(Token, CompareOptions); temp = SubstringFromEnd(Input, (input_length - (index_of_last_token + token_length)), true); if (LeaveToken == false) { return temp; } else { return Token + temp; } default: throw new InvalidEnumArgumentException("Dir", (Int32)Dir, Dir.GetType()); } }
/// <summary> /// Возвращает все искомые подстроки из указанной строки, которые находятся между указанными начальными и конечными токенами. /// Поиск ведётся с начала до конца строки, начиная с указанной позиции, и возвращает все попавшиеся совпадения. /// Если указанных токенов не найдено, возвращает пустой список подстрок. /// </summary> /// <param name="Input">Входная строка, содержащая токены, и внутри которой происходит поиск. Входная строка не может быть NULL, пустой или состоящей из одних пробелов.</param> /// <param name="StartToken">Начальный токен, не может быть NULL или пустой строкой</param> /// <param name="EndToken">Конечный токен, не может быть NULL или пустой строкой</param> /// <param name="StartIndex">Позиция (включительная) начала поиска во входной строке. Если 0 - поиск ведётся с начала. /// Если меньше 0 или больше длины входной строки - выбрасывается исключение.</param> /// <param name="IncludeTokens">Определяет, следует ли включать начальный и конечный токены в возвращаемые подстроки (true) или нет (false)</param> /// <param name="CompOpt">Опции сравнения строк между собой</param> /// <returns>Список подстрок. Если какая-либо из подстрок является пустой (т.е. между начальным и конечным токеном нет ни одного символа), /// в списке она будет представлена значением NULL.</returns> public static List<Substring> GetInnerStringsBetweenTokens(String Input, String StartToken, String EndToken, Int32 StartIndex, Boolean IncludeTokens, StringComparison CompOpt) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (StartToken.IsStringNullOrEmpty() == true) { throw new ArgumentException("Начальный токен не может быть NULL или пустой строкой", "StartToken"); } if (EndToken.IsStringNullOrEmpty() == true) { throw new ArgumentException("Конечный токен не может быть NULL или пустой строкой", "EndToken"); } if (StartIndex < 0) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, "Позиция начала поиска не может быть меньше 0"); } if (StartIndex >= Input.Length) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, String.Format("Позиция начала поиска ('{0}') не может быть больше или равна длине строки ('{1}')", StartIndex, Input.Length)); } if (Enum.IsDefined(typeof(StringComparison), (Int32)CompOpt) == false) { throw new InvalidEnumArgumentException("CompOpt", (Int32)CompOpt, typeof(StringComparison)); } List<Substring> output = new List<Substring>(); Int32 internal_offset = StartIndex; while (true) { Int32 start_token_start_pos = Input.IndexOf(StartToken, internal_offset, CompOpt); if (start_token_start_pos == -1) { return output; } Int32 end_token_start_pos = Input.IndexOf(EndToken, (start_token_start_pos + StartToken.Length), CompOpt); if (end_token_start_pos == -1) { return output; } if (start_token_start_pos + StartToken.Length == end_token_start_pos) { output.Add(null); } else { Int32 substring_start_index; Int32 substring_end_index; if (IncludeTokens == false) { substring_start_index = start_token_start_pos + StartToken.Length; substring_end_index = end_token_start_pos - 1; } else { substring_start_index = start_token_start_pos; substring_end_index = end_token_start_pos - 1 + EndToken.Length; } output.Add(Substring.FromIndexToIndex(Input, substring_start_index, substring_end_index)); } internal_offset = end_token_start_pos + EndToken.Length;//обновление смещения } }
/// <summary> /// Возвращает искомую подстроку из указанной строки, которые находятся между наборами указанных начальных и конечных токенов /// в правильной последовательности. Если каких-либо или всех указанных токенов не найдено, или их реальный порядок не совпадает с указанным, /// возвращается пустой список подстрок. /// </summary> /// <param name="Input">Входная строка, содержащая токены, и внутри которой происходит поиск. Входная строка не может быть NULL, пустой или состоящей из одних пробелов.</param> /// <param name="StartTokens">Список начальных токенов в определённой последовательности, которая будет соблюдена при поиске подстрок. /// Не может быть NULL или пустым, но может содержать единственный элемент.</param> /// <param name="EndTokens">Список конечных токенов в определённой последовательности, которая будет соблюдена при поиске подстрок. /// Не может быть NULL или пустым, но может содержать единственный элемент.</param> /// <param name="EndTokensSearchDirection">Задаёт направление поиска конечных токенов после того, как найдены все начальные. /// FromEndToStart - поиск ведётся от самого конца строки и продвигается до последнего начального токена до тех пор, пока не найдёт все конечные токены. /// FromStartToEnd - поиск ведётся от конца последнего начального токена до конца строки.</param> /// <param name="StartIndex">Позиция (включительная) начала поиска во входной строке. Если 0 - поиск ведётся с начала. /// Если меньше 0 или больше длины входной строки - выбрасывается исключение.</param> /// <param name="CompOpt">Опции сравнения строк между собой</param> /// <exception cref="ArgumentException"></exception> /// <returns>Искомая подстрока. Если не найдена, возвращается NULL.</returns> public static Substring GetInnerStringBetweenTokensSet(String Input, String[] StartTokens, String[] EndTokens, StringTools.Direction EndTokensSearchDirection, Int32 StartIndex, StringComparison CompOpt) { if(Input == null){throw new ArgumentNullException("Input");} if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (StartTokens.IsNullOrEmpty()) { throw new ArgumentException("Список начальных токенов не может быть NULL или пустым", "StartTokens"); } if (EndTokens.IsNullOrEmpty()) { throw new ArgumentException("Список конечных токенов не может быть NULL или пустым", "EndTokens"); } if (StartIndex < 0) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, "Позиция начала поиска не может быть меньше 0"); } if (StartIndex >= Input.Length) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, String.Format("Позиция начала поиска ('{0}') не может быть больше или равна длине строки ('{1}')", StartIndex, Input.Length)); } if (Enum.IsDefined(typeof(StringTools.Direction), EndTokensSearchDirection) == false) { throw new InvalidEnumArgumentException("EndTokensSearchDirection", (Int32)EndTokensSearchDirection, typeof(StringTools.Direction)); } if (Enum.IsDefined(typeof(StringComparison), (Int32)CompOpt) == false) { throw new InvalidEnumArgumentException("CompOpt", (Int32)CompOpt, typeof(StringComparison)); } Int32 internal_offset = StartIndex; for (Int32 one_start_token_index = 0; one_start_token_index < StartTokens.Length; one_start_token_index++) { String current_start_token = StartTokens[one_start_token_index]; Int32 current_start_token_pos = Input.IndexOf(current_start_token, internal_offset, CompOpt); if (current_start_token_pos == -1) { return null; } else { internal_offset = current_start_token_pos + current_start_token.Length; } } Int32 final_substr_start_index = internal_offset; if (EndTokensSearchDirection == StringTools.Direction.FromEndToStart) { Int32 end_offset = Input.Length - 1; for (Int32 one_end_token_index = EndTokens.Length - 1; one_end_token_index >= 0; one_end_token_index--) { String current_end_token = EndTokens[one_end_token_index]; Int32 count_to_search = end_offset - final_substr_start_index; Int32 current_end_token_pos = Input.LastIndexOf(current_end_token, end_offset, count_to_search, CompOpt); if (current_end_token_pos == -1) { return null; } else { end_offset = current_end_token_pos; } } return Substring.FromIndexToIndex(Input, final_substr_start_index, end_offset - 1); } else// if (EndTokensSearchDirection == StringTools.Direction.FromStartToEnd) { Int32 final_substr_end_index = 0; for (Int32 one_end_token_index = 0; one_end_token_index < EndTokens.Length; one_end_token_index++) { String current_end_token = EndTokens[one_end_token_index]; Int32 current_end_token_pos = Input.IndexOf(current_end_token, internal_offset, CompOpt); if (current_end_token_pos == -1) { return null; } internal_offset = current_end_token_pos + current_end_token.Length; if (final_substr_end_index == 0) { final_substr_end_index = current_end_token_pos; } } return Substring.FromIndexToIndex(Input, final_substr_start_index, final_substr_end_index - 1); } }
/// <summary> /// Определяет, является ли входная строка корректным HTML-тэгом и если является, то каким: одиночным, парным открывающим или парным закрывающим. /// </summary> /// <param name="Tag">Строка, предположительно содержащая тэг. Поддерживаются любые строки, включая NULL. Любые символы, кроме пробелов, не являющися часть тэга, приводят к выводу NotTag.</param> /// <param name="TagName">Точное и чёткое имя тэга в нижнем регистре, без кавычек, пробелов и атрибутов, если они есть. Если входная строка не распознана как коректный тэг, содержит NULL.</param> /// <returns>Одно из значений перечисления, определяющее тип тэга</returns> public static HtmlTagType ValidateHtmlTag(String Tag, out String TagName) { TagName = null; if (Tag.IsStringNullEmptyWhiteSpace() == true) { return HtmlTagType.NotTag; } if (StringTools.ContainsHelpers.ContainsAllOf(Tag, new char[2] { '<', '>' }) == false) { return HtmlTagType.NotTag; } String tag_temp = Tag.Trim(); if (tag_temp.StartsWith("<", StringComparison.OrdinalIgnoreCase) == false || tag_temp.EndsWith(">", StringComparison.OrdinalIgnoreCase) == false) { return HtmlTagType.NotTag; } if (StringTools.StringAnalyzers.GetNumberOfOccurencesInString(tag_temp, '<') != 1 || StringTools.StringAnalyzers.GetNumberOfOccurencesInString(tag_temp, '>') != 1) { return HtmlTagType.NotTag; } //На данном этапе тэг коректен. Находим TagName. TagName = StringTools.SubstringHelpers.GetInnerStringsBetweenTokens(Tag, "<", ">", 0, false, StringComparison.OrdinalIgnoreCase).Single().Value; TagName = TagName.Replace("/", String.Empty); if (TagName.Contains(" ", StringComparison.OrdinalIgnoreCase) == true) { TagName = TagName.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).First(); } tag_temp = StringTools.SubstringHelpers.GetInnerStringsBetweenTokens(tag_temp, "<", ">", 0, false, StringComparison.OrdinalIgnoreCase).Single().Value.Trim(); if (tag_temp.IndexOf('/') == 0 && tag_temp.LastIndexOf('/') == tag_temp.Length - 1) { return HtmlTagType.NotTag; } if (tag_temp.LastIndexOf('/') == tag_temp.Length - 1) { return HtmlTagType.Single; } if (tag_temp.IndexOf('/') == 0) { return HtmlTagType.PairClose; } return HtmlTagType.PairOpen; }
/// <summary> /// Удаляет из входной строки указанную начальную и конечную подстроки, если они есть. Если нет хотя бы одной из них, то возвращается исходная строка. /// Если во входной строке содержится множество вложенных один в другой начальных и конечных токенов, метод удалит их все рекурсивно. /// </summary> /// <param name="Input">Входная строка, из которой необходимо удалить все указанные начальные и конечные токены.</param> /// <param name="StartToken">Начальный токен</param> /// <param name="EndToken">Конечный токен</param> /// <param name="CompOpt"></param> /// <returns>Новая строка, содержащая копию старой с удалёнными токенами</returns> public static String DeleteStartAndEndTokens(String Input, String StartToken, String EndToken, StringComparison CompOpt) { if (StartToken.IsNullOrEmpty() == true) { throw new ArgumentException("Начальный токен не может быть NULL или пустой строкой", "Input"); } if (EndToken == null) { throw new ArgumentException("Конечный токен не может быть NULL или пустой строкой", "EndToken"); } if (Input.IsStringNullEmptyWhiteSpace() == true) { return Input; } if (Input.StartsWith(StartToken, CompOpt) == true && Input.EndsWith(EndToken, CompOpt) == true) { Input = Input.Remove(0, StartToken.Length); Input = Input.Remove(Input.Length - EndToken.Length, EndToken.Length); return DeleteStartAndEndTokens(Input, StartToken, EndToken, CompOpt); } else { return Input; } }
/// <summary> /// Возвращает список позиций (индексов) всех вхождений указанного токена в указанной строке /// </summary> /// <param name="Input">Строка, в которой ищутся вхождения подстроки (токена)</param> /// <param name="Token">Подстрока (токен), вхождения которой ищутся в строке</param> /// <param name="CompareOption">Опция сравнения строк между собой</param> /// <returns></returns> public static List<Int32> GetPositionsOfTokenInString(String Input, String Token, StringComparison CompareOption) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (Token.IsStringNullOrEmpty() == true) { throw new ArgumentException("Токен не может быть NULL или пустой строкой", "Token"); } if (String.Compare(Input, Token, CompareOption) == 0) { throw new ArgumentException("Входная строка не может быть равна токену"); } if (Input.Contains(Token, CompareOption) == false) { throw new ArgumentException("Токен не найден во входной строке", "Token"); } UInt32 backup_count = 0; List<Int32> output = new List<int>(); Int32 start_index = -1; while (true) { Int32 current_index = Input.IndexOf(Token, start_index + 1, CompareOption); if (current_index < 0) { break; } else { start_index = current_index; output.Add(current_index); } //backup backup_count++; if (backup_count == UInt32.MaxValue) { throw new InvalidOperationException(String.Format("Предположительно вечный цикл: количество итераций достигло {0} при длине входной строки в {1} символов.", UInt32.MaxValue, Input.Length)); } } return output; }
/// <summary> /// Возвращает одно ближайшее целое положительное число, извлечённое из подстроки, которая вычленяется из входной строки из указанной позиции. /// Если входная строка не содержит цифр вообще, возвращает NULL. /// </summary> /// <param name="Input">Входная строка</param> /// <param name="StartPosition">Позиция (индекс, начинается с 0), начиная с которой, в исходной строке следует проводить поиск. Если равно 0, в поиске участвует вся исходная строка</param> /// <param name="FindPosition">Выводной параметр. Позиция (индекс, начинается с 0) в исходной строке, в которой обнаружилось начало первого попавшегося числа. Если искомое число не обнаружилось, возвращает -1.</param> /// <returns></returns> public static Nullable<UInt32> GetNearestUnsignedIntegerFromString(String Input, Int32 StartPosition, out Int32 FindPosition) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } Int32 input_length = Input.Length; Char[] input_array_cropped = Input.ToCharArray(StartPosition, (input_length - StartPosition)); FindPosition = -1; bool found = false; String number = string.Empty; for (Int32 i = 0; i < input_array_cropped.Length; i++) { if (Char.IsDigit(input_array_cropped[i]) == true) { number = number + input_array_cropped[i].ToString(); found = true; if (FindPosition == -1) { FindPosition = StartPosition + i; } } else if (Char.IsDigit(input_array_cropped[i]) == false && found == true) { break; } } if (number == string.Empty) { return null; } else { UInt32 output = UInt32.Parse(number); if (output != 0) { foreach (char c in number.ToCharArray()) { if (c == '0') { FindPosition++; } else { break; } } } return output; } }
/// <summary> /// Возвращает количество вхождений указанной искомой подстроки во входной строке /// </summary> /// <param name="Input">Строка, в которой ищутся вхождения подстроки. Если NULL или пустая - генерируется исключение.</param> /// <param name="Seek">Искомая подстрока, вхождения которой ищутся в строке</param> /// <param name="CompareOption">Опции поиска подстроки</param> /// <returns></returns> public static Int32 GetNumberOfOccurencesInString(String Input, String Seek, StringComparison CompareOption) { if (Input.IsStringNullEmptyWhiteSpace() == true) throw new ArgumentException("Input string must have a correct value", "Input"); if (String.IsNullOrEmpty(Seek) == true) throw new ArgumentException("Seeking string must not be NULL or empty", "Seek"); Int32 seek_len = Seek.Length; Int32 result = 0; Int32 start_index = 0; while (true) { Int32 current_index = Input.IndexOf(Seek, start_index, CompareOption); if (current_index < 0) { break; } else { result++; start_index = current_index + seek_len; } } return result; }
/// <summary> /// Возвращает входную строку, из которой удалены все подстроки, начинающиеся с указанного начального токена /// и заканчивающиеся ближайшим указанным конечным токеном. /// </summary> /// <param name="Input">Входящая строка, в которой происходит поиск.</param> /// <param name="StartToken">Начальный токен (подстрока), которым начинается удаляемая подстрока. Не может быть NULL или пустым.</param> /// <param name="EndToken">Конечный токен (подстрока), которым оканчивается удаляемая подстрока. Не может быть NULL или пустым.</param> /// <param name="RemoveTokens">Определяет, следует ли удалить начальный и конечный токены вместе с удаляемой подстрокой (true) или же их следует оставить (false)</param> /// <param name="ComparisonType">Опции сравнения строк между собой</param> /// <returns>Новая строка. Если не найдено ни одной пары начальныго и конечного токенов, возвращается оригинальная строка. /// Если начальный и конечный токены одинаковы, или исходная строка является NULL, пустой строкой либо содержит лишь пробелы, /// либо хотя бы один из токенов является NULL или пустой строкой, метод выбрасывает исключение.</returns> public static String RemoveFromStartToEndToken(String Input, String StartToken, String EndToken, Boolean RemoveTokens, StringComparison ComparisonType) { if (Input.IsStringNullEmptyWhiteSpace() == true) throw new ArgumentException("Входная строка является NULL, пустой строкой либо состоит лишь из одних пробелов", "Input"); if (StartToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Начальный токен является NULL или пустой строкой", "StartToken"); if (EndToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Конечный токен является NULL или пустой строкой", "EndToken"); if (String.Compare(StartToken, EndToken, ComparisonType) == 0) { throw new ArgumentException("Начальный и конечный токены должны быть разными с учётом указнных опций сравнения"); } Int32 current_offset = 0; StringBuilder sb = new StringBuilder(Input.Length); while (true) { Int32 start_index = Input.IndexOf(StartToken, current_offset, ComparisonType); if (start_index < 0) { break; } Int32 end_index = Input.IndexOf(EndToken, start_index, ComparisonType); if (end_index < 0) { break; } String slice; if (RemoveTokens) { slice = Input.SubstringWithEnd(current_offset, start_index); } else { slice = Input.SubstringWithEnd(current_offset, start_index + StartToken.Length) + Input.Substring(end_index, EndToken.Length); } sb.Append(slice); current_offset = end_index + EndToken.Length; } sb.Append(Input.Substring(current_offset)); return sb.ToString(); }
public Boolean StringEmpty(String input) { return input.IsStringNullEmptyWhiteSpace(); }
/// <summary> /// Возвращает исходную строку, в которой обрезана её часть от начала или от конца до ближайшего указанного токена /// </summary> /// <param name="Input">Входящая строка, из которой надо извлечь подстроку</param> /// <param name="Token">Токен, который определяет точку обрезания и также обрезается</param> /// <param name="LeaveToken">Если "true" - ближайший токен будет оставлен. Если "false" - он тоже будет удалён.</param> /// <param name="Dir">Направление, с которого будет обрезана подстрока: из начала или из конца</param> /// <param name="ComparisonType">Опции сравнения строк между собой</param> /// <returns></returns> public static String TruncateToClosestToken(String Input, String Token, Boolean LeaveToken, StringTools.Direction Dir, StringComparison ComparisonType) { if (Input.IsStringNullEmptyWhiteSpace() == true) { throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); } if (Token.IsStringNullOrEmpty() == true) { throw new ArgumentException("Токен не может быть NULL или пустой строкой", "Token"); } if (Enum.IsDefined(ComparisonType.GetType(), ComparisonType) == false) { throw new InvalidEnumArgumentException("ComparisonType", (Int32)ComparisonType, ComparisonType.GetType()); } if (String.Compare(Input, Token, ComparisonType) == 0) { throw new ArgumentException("Входная строка не может быть равна токену"); } if (Input.Contains(Token, ComparisonType) == false) { return Input; } Int32 token_length = Token.Length; switch (Dir) { case StringTools.Direction.FromStartToEnd: Int32 index_of_first_token = Input.IndexOf(Token, ComparisonType); if (LeaveToken == true) { return Input.Remove(0, index_of_first_token); } else { return Input.Remove(0, index_of_first_token + token_length); } case StringTools.Direction.FromEndToStart: Int32 index_of_last_token = Input.LastIndexOf(Token, ComparisonType); if (LeaveToken == true) { return Input.Remove(index_of_last_token + token_length); } else { return Input.Remove(index_of_last_token); } default: throw new InvalidEnumArgumentException("Dir", (Int32)Dir, Dir.GetType()); } }
/// <summary> /// Возвращает искомую подстроку из указанной исходной строки, которая размещена между указанным начальным и конечным токеном. /// Ведёт поиск токенов от начала или он указанной начальной позиции до конца строки, и возвращает первое попавшееся совпадение. /// Если указанных токенов не найдено, возвращает NULL. /// </summary> /// <param name="Input">Входная строка, содержащая токены, и внутри которой происходит поиск. Не может быть NULL, пустой или состоящей из одних пробелов.</param> /// <param name="StartToken">Начальный токен. Не может быть NULL или пустой строкой.</param> /// <param name="EndToken">Конечный токен. Не может быть NULL или пустой строкой.</param> /// <param name="StartIndex">Начальная позиция исходной строки, с которой включительно начинается поиск. Если 0 - поиск ведётся с начала. /// Если меньше 0 или больше длины исходной строки, выбрасывается исключение.</param> /// <param name="EndIndex">Конечная позиция исходной строки, на которой включительно останавливается поиск и за которую не выходит. /// Если больше фактической длины строки, 0 или меньше 0, поиск ведётся до конца строки. /// Если больше нуля и меньше или равно ненулевой начальной позиции, выбрасывается исключение.</param> /// <param name="IncludeTokens">Определяет, следует ли включать начальный и конечный токены в возвращаемую подстроку (true) или нет (false)</param> /// <param name="EndTokenSearchDirection">Задаёт направление поиска конечного токена после того, как найден начальный. /// FromEndToStart - поиск ведётся от самого конца входной строки и продвигается до найденного начального токена до тех пор, пока не найдёт конечный токен. /// FromStartToEnd - поиск ведётся от конца найденного начального токена до конца входной строки.</param> /// <param name="ComparisonType">Опции сравнения строк между собой</param> /// <returns>NULL - если не нашло</returns> public static Substring GetInnerStringBetweenTokens(String Input, String StartToken, String EndToken, Int32 StartIndex, Int32 EndIndex, Boolean IncludeTokens, StringTools.Direction EndTokenSearchDirection, StringComparison ComparisonType) { if (Input.IsStringNullEmptyWhiteSpace() == true) throw new ArgumentException("Входная строка не может быть NULL, пустой или состоящей из одних пробелов", "Input"); if (StartToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Начальный токен не может быть NULL или пустой строкой", "StartToken"); if (EndToken.IsStringNullOrEmpty() == true) throw new ArgumentException("Конечный токен не может быть NULL или пустой строкой", "EndToken"); if (StartIndex < 0) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, "Начальная позиция не может быть меньше 0"); } if (StartIndex >= Input.Length) { throw new ArgumentOutOfRangeException("StartIndex", StartIndex, String.Format("Начальная позиция ('{0}') не может быть больше или равна длине строки ('{1}')", StartIndex, Input.Length)); } if (EndIndex <= 0 || EndIndex >= Input.Length) { EndIndex = Input.Length - 1; } if (EndIndex <= StartIndex) { throw new ArgumentOutOfRangeException("EndIndex", EndIndex, String.Format("Конечная позиция ('{0}') не может быть меньше или равна начальной позиции ('{1}')", EndIndex, StartIndex)); } if (Enum.IsDefined(EndTokenSearchDirection.GetType(), EndTokenSearchDirection) == false) { throw new InvalidEnumArgumentException("EndTokenSearchDirection", (Int32)EndTokenSearchDirection, EndTokenSearchDirection.GetType()); } if (Enum.IsDefined(typeof(StringComparison), ComparisonType) == false) { throw new InvalidEnumArgumentException("ComparisonType", (Int32)ComparisonType, typeof(StringComparison)); } Int32 start_token_start_pos = Input.IndexOf(StartToken, StartIndex, (EndIndex - StartIndex + 1), ComparisonType); if (start_token_start_pos == -1) { return null; } Int32 end_token_start_pos; if (EndTokenSearchDirection == StringTools.Direction.FromStartToEnd) { Int32 search_start_index = start_token_start_pos + StartToken.Length; Int32 count = EndIndex - search_start_index + 1; end_token_start_pos = Input.IndexOf(EndToken, search_start_index, count, ComparisonType); } else// if (EndTokenSearchDirection == StringTools.Direction.FromEndToStart) { Int32 start_index = EndIndex; Int32 count = EndIndex - start_token_start_pos + StartToken.Length; end_token_start_pos = Input.LastIndexOf(EndToken, start_index, count, ComparisonType); } if (end_token_start_pos == -1) { return null; } Substring output; if (IncludeTokens == false) { output = Substring.FromIndexToIndex(Input, start_token_start_pos + StartToken.Length, end_token_start_pos - 1); } else { output = Substring.FromIndexToIndex(Input, start_token_start_pos, end_token_start_pos + EndToken.Length - 1); } return output; }
/// <summary> /// Устанавливает новое или дополняет существующее текстовое сообщение о выполнении процесса /// </summary> /// <param name="SetOrAppend">true - set; false - append</param> /// <param name="Message"></param> private void SetOrAppendMessage(Boolean SetOrAppend, String Message) { if (this.rtb_DownloadFailed.InvokeRequired == false) { if (SetOrAppend == true) { this.rtb_DownloadFailed.Text = Message.IsStringNullEmptyWhiteSpace() == true ? "" : Message; } else { if (Message.HasVisibleChars() == false) {return;} this.rtb_DownloadFailed.Text = this.rtb_DownloadFailed.Text + "\r\n" + Message; } } else { this.rtb_DownloadFailed.Invoke((Action<Boolean, String>) this.SetOrAppendMessage, SetOrAppend, Message); } }
/// <summary> /// Анализирует входную XML-разметку на наличие некорректных парных тэгов, и если такие найдены, то исправляет их в корректной последовательности. /// Если во входной строке нет некорректных парных тэгов или нет тэгов вообще, метод возвращает её без изменений. /// </summary> /// <param name="InputXML">Входная строка, содержащая предположительно некорректную XML-разметку</param> /// <returns>Гарантированно корректная XML-разметка</returns> public static String FixBrokenXMLTags(String InputXML) { if (InputXML.IsStringNullEmptyWhiteSpace() == true) { return InputXML; } if (StringTools.ContainsHelpers.ContainsAllOf(InputXML, new char[] { '<', '>' }) == false) { return InputXML; } List<Substring> tags_with_positions = StringTools.SubstringHelpers.GetInnerStringsBetweenTokens (InputXML, "<", ">", 0, false, StringComparison.OrdinalIgnoreCase); if (tags_with_positions.Any() == false) { return InputXML; } StringBuilder output = new StringBuilder(InputXML.Length); Stack<String> open_tags = new Stack<String>(); Int32 start_position = 0; foreach (Substring one_possible_tag in tags_with_positions) { String tag_name; HtmlTools.HtmlTagType tag_type = HtmlTools.ValidateHtmlTag("<" + one_possible_tag.Value + ">", out tag_name); if (tag_type != HtmlTagType.PairClose)//если предполагаемый тэг не является тэгом, или одиночный, или парный открывающий { //добавляем в выводную строку часть исходной строки, начиная от позиции поиска и заканчивая концом просканированной части output.Append(InputXML.SubstringWithEnd(start_position, one_possible_tag.StartIndex + one_possible_tag.Value.Length + 1)); //устанавливаем новое значение позиции поиска, равное позиции начала вхождения тела потенциального тэга и заканчивая концом закрывающей скобки, следуемой после тела потенциального тэга start_position = one_possible_tag.StartIndex + one_possible_tag.Value.Length + 1; if (tag_type == HtmlTagType.PairOpen)//если предполагаемый тэг является парным открывающим { open_tags.Push(tag_name);//добавляем его в стэк } } else//если предполагаемый тэг является парным закрывающим { if (open_tags.Any() == false || open_tags.Peek() != tag_name)//закрывающий тэг не соответствует последнему открывающему или нет незакрытых тэгов { //добавляем в выводную строку часть исходной строки, начиная от позиции поиска и заканчивая началом открывающей скобки неоткрытого закрывающего тэга if (one_possible_tag.StartIndex - 1 > start_position) { output.Append(InputXML.SubstringWithEnd(start_position, one_possible_tag.StartIndex - 1)); } //устанавливаем новое значение позиции поиска, равное позиции начала вхождения тела потенциального тэга и заканчивая концом закрывающей скобки, //следуемой после тела потенциального тэга start_position = one_possible_tag.StartIndex + one_possible_tag.Value.Length + 1; } else//закрывающий тэг соответствует последнему открывающему { //удалить открывающий из стэка open_tags.Pop(); //добавляем в выводную строку часть исходной строки, начиная от позиции поиска и заканчивая концом просканированной части output.Append(InputXML.SubstringWithEnd(start_position, one_possible_tag.StartIndex + one_possible_tag.Value.Length + 1)); //устанавливаем новое значение позиции поиска, равное позиции начала вхождения тела потенциального тэга и заканчивая концом закрывающей скобки, //следуемой после тела потенциального тэга start_position = one_possible_tag.StartIndex + one_possible_tag.Value.Length + 1; } } } if (start_position < InputXML.Length) { output.Append(InputXML.Substring(start_position)); } while (open_tags.Any() == true) { output.Append("</" + open_tags.Pop() + ">"); } return output.ToString(); }