PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/wojilu/_wojilu/strUtil.cs

https://bitbucket.org/kingshine/wojilu
C# | 654 lines | 305 code | 99 blank | 250 comment | 137 complexity | 1ff7b61f13884c91141ae09b8d1658d5 MD5 | raw file
Possible License(s): MIT
  1. /*
  2. * Copyright 2010 www.wojilu.com
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Text.RegularExpressions;
  20. using System.Threading;
  21. using System.Web.Configuration;
  22. using System.Web.Security;
  23. using System.Text;
  24. namespace wojilu {
  25. /// <summary>
  26. /// 字符串工具类,封装了常见字符串操作
  27. /// </summary>
  28. public class strUtil {
  29. private static Regex htmlReg = new Regex( "<[^>]*>" );
  30. /// <summary>
  31. /// 检查字符串是否是 null 或者空白字符。不同于.net自带的string.IsNullOrEmpty,多个空格在这里也返回true。
  32. /// </summary>
  33. /// <param name="target"></param>
  34. /// <returns></returns>
  35. public static Boolean IsNullOrEmpty( String target ) {
  36. if (target != null) {
  37. return target.Trim().Length == 0;
  38. }
  39. return true;
  40. }
  41. /// <summary>
  42. /// 检查是否包含有效字符(空格等空白字符不算)
  43. /// </summary>
  44. /// <param name="target"></param>
  45. /// <returns></returns>
  46. public static Boolean HasText( String target ) {
  47. return !IsNullOrEmpty( target );
  48. }
  49. /// <summary>
  50. /// 比较两个字符串是否相等
  51. /// </summary>
  52. /// <param name="s1"></param>
  53. /// <param name="s2"></param>
  54. /// <returns></returns>
  55. public static Boolean Equals( String s1, String s2 ) {
  56. if (s1 == null && s2 == null) return true;
  57. if (s1 == null || s2 == null) return false;
  58. if (s2.Length != s1.Length) return false;
  59. return string.Compare( s1, 0, s2, 0, s2.Length ) == 0;
  60. }
  61. /// <summary>
  62. /// 比较两个字符串是否相等(不区分大小写)
  63. /// </summary>
  64. /// <param name="s1"></param>
  65. /// <param name="s2"></param>
  66. /// <returns></returns>
  67. public static Boolean EqualsIgnoreCase( String s1, String s2 ) {
  68. if (s1 == null && s2 == null) return true;
  69. if (s1 == null || s2 == null) return false;
  70. if (s2.Length != s1.Length) return false;
  71. return string.Compare( s1, 0, s2, 0, s2.Length, StringComparison.OrdinalIgnoreCase ) == 0;
  72. }
  73. /// <summary>
  74. /// 将 endString 附加到 srcString末尾,如果 srcString 末尾已包含 endString,则不再附加。
  75. /// </summary>
  76. /// <param name="srcString"></param>
  77. /// <param name="endString"></param>
  78. /// <returns></returns>
  79. public static String Append( String srcString, String endString ) {
  80. if (strUtil.IsNullOrEmpty( srcString )) return endString;
  81. if (strUtil.IsNullOrEmpty( endString )) return srcString;
  82. if (srcString.EndsWith( endString )) return srcString;
  83. return srcString + endString;
  84. }
  85. /// <summary>
  86. /// 将对象转为字符串,如果对象为 null,则转为空字符串(string.Empty)
  87. /// </summary>
  88. /// <param name="str"></param>
  89. /// <returns></returns>
  90. public static String ConverToNotNull( Object str ) {
  91. if (str == null) return "";
  92. return str.ToString();
  93. }
  94. /// <summary>
  95. /// 从字符串中截取指定长度的一段,如果源字符串被截取了,则结果末尾出现省略号...
  96. /// </summary>
  97. /// <param name="str">源字符串</param>
  98. /// <param name="length">需要截取的长度</param>
  99. /// <returns></returns>
  100. public static String CutString( Object str, int length ) {
  101. return CutString( ConverToNotNull( str ), length );
  102. }
  103. /// <summary>
  104. /// 从字符串中截取指定长度的一段,如果源字符串被截取了,则结果末尾出现省略号...
  105. /// </summary>
  106. /// <param name="str">源字符串</param>
  107. /// <param name="length">需要截取的长度</param>
  108. /// <returns></returns>
  109. public static String CutString( String str, int length ) {
  110. if (str == null) return null;
  111. if (str.Length > length) return String.Format( "{0}...", str.Substring( 0, length ) );
  112. return str;
  113. }
  114. /// <summary>
  115. /// 将字符串转换为编辑器中可用的字符串(替换掉换行符号)
  116. /// </summary>
  117. /// <param name="str"></param>
  118. /// <returns></returns>
  119. public static String Edit( String str ) {
  120. return str.Replace( "\n", "" ).Replace( "\r", "" ).Replace( "'", "&#39;" );
  121. }
  122. /// <summary>
  123. /// 对双引号进行编码
  124. /// </summary>
  125. /// <param name="src"></param>
  126. /// <returns></returns>
  127. public static String EncodeQuote( String src ) {
  128. return src.Replace( "\"", "&quot;" );
  129. }
  130. /// <summary>
  131. /// 让 html 在 textarea 中正常显示。替换尖括号和字符&amp;lt;与&amp;gt;
  132. /// </summary>
  133. /// <param name="html"></param>
  134. /// <returns></returns>
  135. public static String EncodeTextarea( String html ) {
  136. if (html == null) return null;
  137. return html.Replace( "&lt;", "&amp;lt;" ).Replace( "&gt;", "&amp;gt;" ).Replace( "<", "&lt;" ).Replace( ">", "&gt;" );
  138. }
  139. ///// <summary>
  140. ///// 对双引号进行编码,并替换掉换行符
  141. ///// </summary>
  142. ///// <param name="src"></param>
  143. ///// <returns></returns>
  144. //public static String EncodeQuoteAndClearLine( String src ) {
  145. // return src.Replace( "\"", "\\\"" ).Replace( "\r\n", "" ).Replace( "\n", "" ).Replace( "\r", "" ).Replace( "\r\n", "" );
  146. //}
  147. /// <summary>
  148. /// 截取字符串末尾的整数
  149. /// </summary>
  150. /// <param name="rawString"></param>
  151. /// <returns></returns>
  152. public static int GetEndNumber( String rawString ) {
  153. if (IsNullOrEmpty( rawString )) return 0;
  154. char[] chArray = rawString.ToCharArray();
  155. int startIndex = -1;
  156. for (int i = chArray.Length - 1; i >= 0; i--) {
  157. if (!char.IsDigit( chArray[i] )) break;
  158. startIndex = i;
  159. }
  160. if (startIndex == -1) return 0;
  161. return cvt.ToInt( rawString.Substring( startIndex ) );
  162. }
  163. /// <summary>
  164. /// 获取 html 文档的标题内容
  165. /// </summary>
  166. /// <param name="html"></param>
  167. /// <returns></returns>
  168. public String getHtmlTitle( String html ) {
  169. Match match = Regex.Match( html, "<title>(.*)</title>" );
  170. if (match.Groups.Count == 2) return match.Groups[1].Value;
  171. return "(unknown)";
  172. }
  173. /// <summary>
  174. /// 将整数按照指定的长度转换为字符串,比如33转换为6位就是"000033"
  175. /// </summary>
  176. /// <param name="intValue"></param>
  177. /// <param name="length"></param>
  178. /// <returns></returns>
  179. public static String GetIntString( int intValue, int length ) {
  180. return String.Format( "{0:D" + length + "}", intValue );
  181. }
  182. /// <summary>
  183. /// 得到字符串的 TitleCase 格式
  184. /// </summary>
  185. /// <param name="str"></param>
  186. /// <returns></returns>
  187. public static String GetTitleCase( String str ) {
  188. return Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase( str );
  189. }
  190. /// <summary>
  191. /// 得到字符串的 CamelCase 格式
  192. /// </summary>
  193. /// <param name="str"></param>
  194. /// <returns></returns>
  195. public static String GetCamelCase( String str ) {
  196. if (IsNullOrEmpty( str )) return str;
  197. return str[0].ToString().ToLower() + str.Substring( 1 );
  198. }
  199. /// <summary>
  200. /// 根据对象(IEntity)列表,获取所有对象的ids字符串
  201. /// </summary>
  202. /// <param name="objList">对象必须是IEntity接口</param>
  203. /// <returns>比如 2,5,8 等</returns>
  204. public static string GetIds( IList objList ) {
  205. if (objList == null || objList.Count == 0) return "";
  206. String ids = "";
  207. foreach (IEntity obj in objList) {
  208. if (obj == null || obj.Id == 0) continue;
  209. ids += obj.Id + ",";
  210. }
  211. return ids.TrimEnd( ',' );
  212. }
  213. /// <summary>
  214. /// 从类型的全名中获取类型名称(不包括命名空间)
  215. /// </summary>
  216. /// <param name="typeFullName"></param>
  217. /// <returns></returns>
  218. public static String GetTypeName( String typeFullName ) {
  219. String[] strArray = typeFullName.Split( new char[] { '.' } );
  220. return strArray[strArray.Length - 1];
  221. }
  222. /// <summary>
  223. /// 获取类型名称(主要针对泛型做特殊处理)。如果要获取内部元素信息,请使用t.GetGenericArguments
  224. /// </summary>
  225. /// <param name="t"></param>
  226. /// <returns></returns>
  227. public static String GetTypeName( Type t ) {
  228. if (t.IsGenericType == false) return t.Name;
  229. return t.Name.Split( '`' )[0];
  230. }
  231. /// <summary>
  232. /// 获取类型全名(主要针对泛型做特殊处理),比如List&lt;String&gt;返回System.Collections.Generic.List。如果要获取内部元素信息,请使用t.GetGenericArguments
  233. /// </summary>
  234. /// <param name="t"></param>
  235. /// <returns></returns>
  236. public static String GetTypeFullName( Type t ) {
  237. if (t.IsGenericType == false) return t.FullName;
  238. return t.FullName.Split( '`' )[0];
  239. }
  240. /// <summary>
  241. /// 返回泛型的类型全名,包括元素名,比如System.Collections.Generic.List&lt;System.String&gt;
  242. /// </summary>
  243. /// <param name="t"></param>
  244. /// <returns></returns>
  245. public static String GetGenericTypeWithArgs( Type t ) {
  246. //System.Collections.Generic.Dictionary`2[System.Int32,System.String]
  247. String[] arr = t.ToString().Split( '`' );
  248. String[] arrArgs = arr[1].Split( '[' );
  249. String args = "<" + arrArgs[1].TrimEnd( ']' ) + ">";
  250. return arr[0] + args;
  251. }
  252. /// <summary>
  253. /// 是否是英文字符和下划线
  254. /// </summary>
  255. /// <param name="rawString"></param>
  256. /// <returns></returns>
  257. public static Boolean IsLetter( String rawString ) {
  258. if (IsNullOrEmpty( rawString )) return false;
  259. char[] arrChar = rawString.ToCharArray();
  260. foreach (char c in arrChar) {
  261. if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".IndexOf( c ) < 0)
  262. return false;
  263. }
  264. return true;
  265. }
  266. /// <summary>
  267. /// 是否是英文、数字和下划线,但不能以下划线开头
  268. /// </summary>
  269. /// <param name="rawString"></param>
  270. /// <returns></returns>
  271. public static Boolean IsUrlItem( String rawString ) {
  272. if (IsNullOrEmpty( rawString )) return false;
  273. char[] arrChar = rawString.ToCharArray();
  274. if (arrChar[0] == '_') return false;
  275. foreach (char c in arrChar) {
  276. if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890".IndexOf( c ) < 0)
  277. return false;
  278. }
  279. return true;
  280. }
  281. /// <summary>
  282. /// 是否全部都是中文字符
  283. /// </summary>
  284. /// <param name="str"></param>
  285. /// <returns></returns>
  286. public static Boolean IsChineseLetter( String str ) {
  287. if (strUtil.IsNullOrEmpty( str )) return false;
  288. char[] arr = str.ToCharArray();
  289. for (int i = 0; i < arr.Length; i++) {
  290. if (IsChineseLetter( str, i ) == false) return false;
  291. }
  292. return true;
  293. }
  294. /// <summary>
  295. /// 只能以英文或中文开头,允许英文、数字、下划线和中文;
  296. /// </summary>
  297. /// <param name="str"></param>
  298. /// <returns></returns>
  299. public static Boolean IsAbcNumberAndChineseLetter( String str ) {
  300. if (strUtil.IsNullOrEmpty( str )) return false;
  301. char[] arr = str.ToCharArray();
  302. if (isAbcAndChinese( arr[0] ) == false) return false;
  303. for (int i = 0; i < arr.Length; i++) {
  304. if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890".IndexOf( arr[i] ) >= 0) continue;
  305. if (IsChineseLetter( str, i ) == false) return false;
  306. }
  307. return true;
  308. }
  309. private static Boolean isAbcAndChinese( char c ) {
  310. if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf( c ) >= 0) return true;
  311. if (IsChineseLetter( c.ToString(), 0 ) == true) return true;
  312. return false;
  313. }
  314. private static Boolean IsChineseLetter( String input, int index ) {
  315. int chineseCharBegin = Convert.ToInt32( 0x4e00 );
  316. int chineseCharEnd = Convert.ToInt32( 0x9fff );
  317. int code = Char.ConvertToUtf32( input, index );
  318. return (code >= chineseCharBegin && code <= chineseCharEnd);
  319. }
  320. /// <summary>
  321. /// 是否是有效的颜色值(3位或6位,全部由英文字符或数字组成)
  322. /// </summary>
  323. /// <param name="aColor"></param>
  324. /// <returns></returns>
  325. public static Boolean IsColorValue( String aColor ) {
  326. if (strUtil.IsNullOrEmpty( aColor )) return false;
  327. String color = aColor.Trim().TrimStart( '#' ).Trim();
  328. if (color.Length != 3 && color.Length != 6) return false;
  329. char[] arr = color.ToCharArray();
  330. foreach (char c in arr) {
  331. if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".IndexOf( c ) < 0) return false;
  332. }
  333. return true;
  334. }
  335. /// <summary>
  336. /// 用斜杠/拼接两个字符串
  337. /// </summary>
  338. /// <param name="strA"></param>
  339. /// <param name="strB"></param>
  340. /// <returns></returns>
  341. public static String Join( String strA, String strB ) {
  342. return Join( strA, strB, "/" );
  343. }
  344. /// <summary>
  345. /// 根据制定的分隔符拼接两个字符串
  346. /// </summary>
  347. /// <param name="strA"></param>
  348. /// <param name="strB"></param>
  349. /// <param name="separator"></param>
  350. /// <returns></returns>
  351. public static String Join( String strA, String strB, String separator ) {
  352. return (Append( strA, separator ) + TrimStart( strB, separator ));
  353. }
  354. /// <summary>
  355. /// 剔除 html 中的 tag
  356. /// </summary>
  357. /// <param name="html"></param>
  358. /// <returns></returns>
  359. public static String ParseHtml( Object html ) {
  360. if (html == null) return String.Empty;
  361. return htmlReg.Replace( html.ToString(), "" ).Replace( " ", " " );
  362. }
  363. /// <summary>
  364. /// 剔除 html 中的 tag,并返回指定长度的字符串
  365. /// </summary>
  366. /// <param name="html"></param>
  367. /// <param name="count"></param>
  368. /// <returns></returns>
  369. public static String ParseHtml( Object html, int count ) {
  370. return CutString( ParseHtml( html ), count ).Replace( " ", "" );
  371. }
  372. /// <summary>
  373. /// 从 html 中截取指定长度的一段,并关闭未结束的 html 标签
  374. /// </summary>
  375. /// <param name="html"></param>
  376. /// <param name="count">需要截取的长度(小于20个字符按20个字符计算)</param>
  377. /// <returns></returns>
  378. public static String CutHtmlAndColse( String html, int count ) {
  379. if (html == null) return "";
  380. html = html.Trim();
  381. if (count <= 0) return "";
  382. if (count < 20) count = 20;
  383. String unclosedHtml = html.Length <= count ? html : html.Trim().Substring( 0, count );
  384. return CloseHtml( unclosedHtml );
  385. }
  386. /// <summary>
  387. /// 关闭未结束的 html 标签
  388. /// (TODO 本方法临时使用,待重写)
  389. /// </summary>
  390. /// <param name="unClosedHtml"></param>
  391. /// <returns></returns>
  392. public static String CloseHtml( String unClosedHtml ) {
  393. if (unClosedHtml == null) return "";
  394. String[] arrTags = new String[] { "strong", "b", "i", "u", "em", "font", "span", "label", "pre", "td", "th", "tr", "tbody", "table", "li", "ul", "ol", "h1", "h2", "h3", "h4", "h5", "h6", "p", "div" };
  395. for (int i = 0; i < arrTags.Length; i++) {
  396. Regex re = new Regex( "<" + arrTags[i] + "[^>]*>", RegexOptions.IgnoreCase );
  397. int openCount = re.Matches( unClosedHtml ).Count;
  398. if (openCount == 0) continue;
  399. re = new Regex( "</" + arrTags[i] + ">", RegexOptions.IgnoreCase );
  400. int closeCount = re.Matches( unClosedHtml ).Count;
  401. int unClosedCount = openCount - closeCount;
  402. for (int k = 0; k < unClosedCount; k++) {
  403. unClosedHtml += "</" + arrTags[i] + ">";
  404. }
  405. }
  406. return unClosedHtml;
  407. }
  408. /// <summary>
  409. /// 将字符串分割成数组
  410. /// </summary>
  411. /// <param name="srcString"></param>
  412. /// <param name="separator"></param>
  413. /// <returns></returns>
  414. public static String[] Split( String srcString, String separator ) {
  415. if (srcString == null) return null;
  416. if (separator == null) throw new ArgumentNullException();
  417. return srcString.Split( new String[] { separator }, StringSplitOptions.None );
  418. }
  419. /// <summary>
  420. /// 过滤掉 sql 语句中的单引号,并返回指定长度的结果
  421. /// </summary>
  422. /// <param name="rawSql"></param>
  423. /// <param name="number"></param>
  424. /// <returns></returns>
  425. public static String SqlClean( String rawSql, int number ) {
  426. if (IsNullOrEmpty( rawSql )) return rawSql;
  427. return SubString( rawSql, number ).Replace( "'", "''" );
  428. }
  429. /// <summary>
  430. /// 从字符串中截取指定长度的一段,结果末尾没有省略号
  431. /// </summary>
  432. /// <param name="str"></param>
  433. /// <param name="length"></param>
  434. /// <returns></returns>
  435. public static String SubString( String str, int length ) {
  436. if (str == null) return null;
  437. if (str.Length > length) return str.Substring( 0, length );
  438. return str;
  439. }
  440. /// <summary>
  441. /// 将纯文本中的换行符转换成html中换行符
  442. /// </summary>
  443. /// <param name="str"></param>
  444. /// <returns></returns>
  445. public static String Text2Html( String str ) {
  446. return str.Replace( "\n", "<br/>" );
  447. }
  448. /// <summary>
  449. /// 从 srcString 的末尾剔除掉 trimString
  450. /// </summary>
  451. /// <param name="srcString"></param>
  452. /// <param name="trimString"></param>
  453. /// <returns></returns>
  454. public static String TrimEnd( String srcString, String trimString ) {
  455. if (strUtil.IsNullOrEmpty( trimString )) return srcString;
  456. if (srcString.EndsWith( trimString ) == false) return srcString;
  457. if (srcString.Equals( trimString )) return "";
  458. return srcString.Substring( 0, srcString.Length - trimString.Length );
  459. }
  460. /// <summary>
  461. /// 从 srcString 的开头剔除掉 trimString
  462. /// </summary>
  463. /// <param name="srcString"></param>
  464. /// <param name="trimString"></param>
  465. /// <returns></returns>
  466. public static String TrimStart( String srcString, String trimString ) {
  467. if (srcString == null) return null;
  468. if (trimString == null) return srcString;
  469. if (strUtil.IsNullOrEmpty( srcString )) return String.Empty;
  470. if (srcString.StartsWith( trimString ) == false) return srcString;
  471. return srcString.Substring( trimString.Length );
  472. }
  473. /// <summary>
  474. /// 将 html 中的脚本从各个部位,全部挪到页脚,以提高网页加载速度
  475. /// </summary>
  476. /// <param name="html"></param>
  477. /// <returns></returns>
  478. public static String ResetScript( String html ) {
  479. Regex reg = new Regex( "<script.*?</script>", RegexOptions.Singleline );
  480. MatchCollection mlist = reg.Matches( html );
  481. StringBuilder sb = new StringBuilder();
  482. sb.Append( reg.Replace( html, "" ) );
  483. for (int i = 0; i < mlist.Count; i++) {
  484. sb.Append( mlist[i].Value );
  485. }
  486. return sb.ToString();
  487. }
  488. /// <summary>
  489. /// 将字符串分割成平均的n等份,每份长度为count
  490. /// </summary>
  491. /// <param name="str"></param>
  492. /// <param name="count"></param>
  493. /// <returns></returns>
  494. public static List<String> SplitByNum( String str, int count ) {
  495. List<String> list = new List<string>();
  496. if (str == null) return list;
  497. if (str.Length == 0) {
  498. list.Add( str );
  499. return list;
  500. }
  501. if (count <= 0) {
  502. list.Add( str );
  503. return list;
  504. }
  505. int k = 0;
  506. StringBuilder sb = new StringBuilder();
  507. for (int i = 0; i < str.Length; i++) {
  508. if (k == count) {
  509. list.Add( sb.ToString() );
  510. k = 0;
  511. sb = new StringBuilder();
  512. }
  513. sb.Append( str[i] );
  514. k++;
  515. }
  516. if (sb.Length > 0) list.Add( sb.ToString() );
  517. return list;
  518. }
  519. /// <summary>
  520. /// 将 html 中空白字符和空白标记(&amp;nbsp;)剔除掉
  521. /// </summary>
  522. /// <param name="val"></param>
  523. /// <returns></returns>
  524. public static String TrimHtml( String val ) {
  525. if (val == null) return null;
  526. val = val.Trim();
  527. String text = ParseHtml( val );
  528. text = trimHtmlBlank( text );
  529. if (strUtil.IsNullOrEmpty( text ) && hasNotImg( val ) && hasNotFlash( val )) return "";
  530. val = trimHtmlBlank( val );
  531. return val;
  532. }
  533. private static String trimHtmlBlank( String text ) {
  534. if (text == null) return null;
  535. text = text.Trim();
  536. if (text.StartsWith( htmlBlank ) || text.EndsWith( htmlBlank )) {
  537. while (true) {
  538. text = strUtil.TrimStart( text, htmlBlank ).Trim();
  539. text = strUtil.TrimEnd( text, htmlBlank ).Trim();
  540. if (!text.StartsWith( htmlBlank ) && !text.EndsWith( htmlBlank )) break;
  541. }
  542. }
  543. return text;
  544. }
  545. private static Boolean hasNotImg( String val ) {
  546. if (val.ToLower().IndexOf( "<img " ) >= 0) return false;
  547. return true;
  548. }
  549. private static Boolean hasNotFlash( String val ) {
  550. if (val.ToLower().IndexOf( "x-shockwave-flash" ) >= 0) return false;
  551. return true;
  552. }
  553. private static readonly String htmlBlank = "&nbsp;";
  554. }
  555. }