ksString.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. {*******************************************************}
  2. { }
  3. { Methods of Sting }
  4. { }
  5. { CopyRight (C) 2018-2020 KngStr }
  6. { }
  7. { Some Code from }
  8. { QDAC of swish, Inno }
  9. { Thanks }
  10. { }
  11. {*******************************************************}
  12. unit ksString;
  13. interface
  14. /// <summary>
  15. /// 创建空白文件
  16. /// </summary>
  17. function CreateBlankFile(S: string): Boolean;
  18. /// <summary>
  19. /// 自动为已存在文件名加数字
  20. /// </summary>
  21. function AutoChangeFileName(AFile: string): string;
  22. /// <summary>
  23. /// 自动替换文件名中的非法字符为
  24. /// </summary>
  25. procedure ChangeInvalidFileNameChars(var FileName: string; AChar: Char = '_');
  26. /// <summary>
  27. /// 格式化秒为时间,冒号分割
  28. /// </summary>
  29. function FormatSeconds(const AValue: Int64): string; overload;
  30. /// <summary>
  31. /// 格式化秒为时间,冒号分割
  32. /// </summary>
  33. function FormatSeconds(const AValue: Integer): string; overload;
  34. /// <summary>
  35. /// 格式化秒为时间,冒号分割
  36. /// </summary>
  37. function FormatSeconds(const AValue: Double): string; overload;
  38. /// <summary>
  39. /// 格式化文件大小,拷贝自qdac,增加更多单位
  40. /// </summary>
  41. function FormatSize(ASize: Int64): string;
  42. /// <summary>
  43. /// 文件大小字符串转数字
  44. /// 1[b] "1 k[b]" " 1 m[b] " 1g[b] 1t[b]
  45. /// </summary>
  46. function SizeStrToInt(ASize: string; ADefault: Int64 = 0): Int64;
  47. /// <summary>
  48. /// 文件大小单位转数字
  49. /// </summary>
  50. function SizeUnitToInt(AUnit: string): Int64; overload;
  51. /// <summary>
  52. /// 文件大小单位转数字
  53. /// </summary>
  54. function SizeUnitToInt(AUnit: Char): Int64; overload;
  55. /// <summary>
  56. /// 是否中国手机号
  57. /// 13900000000
  58. /// +8613900000000
  59. /// +86 139 0000 0000
  60. /// +86-139-0000-0000
  61. /// </summary>
  62. /// <param name="AOnlyNum">仅允许数字和开头的+</param>
  63. function IsChineseMobileNumber(S: string; AOnlyNum: Boolean = False): Boolean;
  64. {
  65. 文本参数解析,来自Inno
  66. Differences from Delphi's ParamStr:
  67. - No limits on parameter length
  68. - Doesn't ignore empty parameters ("")
  69. - Handles the empty argv[0] case like MSVC: if GetCommandLine() returns
  70. " a b" then NewParamStr(1) should return "a", not "b"
  71. }
  72. /// <summary>
  73. /// 获取指定参数, one-base
  74. /// </summary>
  75. /// <remarks>
  76. /// 按命令行拆分方式
  77. /// </remarks>
  78. function StrParamStr(Command: string; Index: Integer): string; overload;
  79. function StrParamStr(Command: PChar; Index: Integer): string; overload;
  80. /// <summary>
  81. /// 获取参数个数
  82. /// </summary>
  83. /// <remarks>
  84. /// 按命令行拆分方式
  85. /// </remarks>
  86. function StrParamCount(Command: string): Integer; overload;
  87. function StrParamCount(Command: PChar): Integer; overload;
  88. /// <summary>
  89. /// 获取指定命令行参数的值,/x=xxx 和 -x=xxx
  90. /// </summary>
  91. /// <remarks>
  92. /// 按命令行拆分方式
  93. /// </remarks>
  94. function GetStrParamVal(Command: string; const Param, Default: String): String; overload;
  95. function GetStrParamVal(Command: PChar; const Param, Default: String): String; overload;
  96. /// <summary>
  97. /// 获取下一个参数,并返回剩余内容
  98. /// </summary>
  99. /// <remarks>
  100. /// 按命令行拆分方式
  101. /// </remarks>
  102. function GetStrParamStr(P: PChar; var Param: string): PChar;
  103. implementation
  104. uses
  105. {$IFDEF MSWINDOWS}Windows,{$ENDIF}
  106. Classes, SysUtils, IOUtils;
  107. function CreateBlankFile(S: string): Boolean;
  108. var
  109. FStrm: TFileStream;
  110. begin
  111. Result := False;
  112. try
  113. FStrm := TFileStream.Create(S, fmCreate);
  114. if FStrm = nil then
  115. Exit;
  116. Result := True;
  117. FreeAndNil(FStrm);
  118. except
  119. FStrm := nil;
  120. end;
  121. end;
  122. function AutoChangeFileName(AFile: string): string;
  123. var
  124. I: Integer;
  125. sPath, sExt: string;
  126. begin
  127. Result := AFile;
  128. I := 0;
  129. sPath := ChangeFileExt(Result, '');
  130. sExt := ExtractFileExt(Result);
  131. while FileExists(Result) or DirectoryExists(Result) do begin
  132. Inc(I);
  133. Result := Format('%s(%d)%s', [sPath, I, sExt]);
  134. end;
  135. end;
  136. procedure ChangeInvalidFileNameChars(var FileName: string; AChar: Char);
  137. var
  138. PFileName: PChar;
  139. FileNameLen: Integer;
  140. Ch: Char;
  141. I: Integer;
  142. begin
  143. I := 0;
  144. PFileName := PChar(FileName);
  145. FileNameLen := Length(FileName);
  146. while I < FileNameLen do begin
  147. Ch := PFileName[I];
  148. if not TPath.IsValidFileNameChar(Ch) then
  149. PFileName[I] := AChar
  150. else
  151. Inc(I);
  152. end;
  153. end;
  154. function FormatSeconds(const AValue: Double): string; overload;
  155. var
  156. h, m, s, ms: Integer;
  157. begin
  158. ms := Trunc(Frac(AValue) * 1000);
  159. s := Trunc(AValue);
  160. m := s div 60;
  161. h := m div 60;
  162. if h > 0 then
  163. Result := Format('%.2d:%.2d:%.2d.%.3d', [h, m mod 60, s mod 60, ms])
  164. else
  165. Result := Format('%.2d:%.2d.%.3d', [m, s mod 60, ms]);
  166. end;
  167. function FormatSeconds(const AValue: Int64): string;
  168. var
  169. h, m, s: Integer;
  170. begin
  171. s := AValue;
  172. m := s div 60;
  173. h := m div 60;
  174. if h > 0 then
  175. Result := Format('%.2d:%.2d:%.2d', [h, m mod 60, s mod 60])
  176. else
  177. Result := Format('%.2d:%.2d', [m, s mod 60]);
  178. end;
  179. function FormatSeconds(const AValue: Integer): string; overload;
  180. begin
  181. FormatSeconds(Int64(AValue));
  182. end;
  183. function FormatSize(ASize: Int64): string;
  184. var
  185. AIdx, R1, s1: Int64;
  186. AIsNeg: Boolean;
  187. const
  188. Units: array [0 .. 6] of string = ('EB', 'PB', 'TB', 'GB', 'MB', 'KB', 'B');
  189. begin
  190. AIsNeg := (ASize < 0);
  191. AIdx := 6;
  192. R1 := 0;
  193. if AIsNeg then
  194. ASize := -ASize;
  195. Result := '';
  196. while (AIdx >= 0) do
  197. begin
  198. s1 := ASize mod 1024;
  199. ASize := ASize shr 10;
  200. if (ASize = 0) or (AIdx = 0) then
  201. begin
  202. R1 := R1 * 100 div 1024;
  203. if R1 > 0 then
  204. begin
  205. if R1 >= 10 then
  206. Result := IntToStr(s1) + '.' + IntToStr(R1) + Units[AIdx]
  207. else
  208. Result := IntToStr(s1) + '.' + '0' + IntToStr(R1) + Units[AIdx];
  209. end
  210. else
  211. Result := IntToStr(s1) + Units[AIdx];
  212. Break;
  213. end;
  214. R1 := s1;
  215. Dec(AIdx);
  216. end;
  217. if AIsNeg then
  218. Result := '-' + Result;
  219. end;
  220. function IsChineseMobileNumber(S: string; AOnlyNum: Boolean): boolean;
  221. var
  222. p: PChar;
  223. i: Integer;
  224. begin
  225. Result := False;
  226. // 最短肯定是11位
  227. if (Length(S) < 11) then
  228. Exit;
  229. i := 0;
  230. p := PChar(S);
  231. while p^ <> #0 do begin
  232. if p^ = '+' then begin
  233. if i > 0 then // +号必须在第一位
  234. Exit;
  235. if (p[1] = '8') and (p[2] = '6') then // +86,而且是连续的
  236. Inc(p, 3)
  237. else
  238. Exit;
  239. end
  240. else if ((p^ >= '0') and (p^ <= '9')) then begin
  241. if (i = 0) and (p^ <> '1') then // 中国手机号都是1开头
  242. Exit;
  243. Inc(p);
  244. Inc(i);
  245. end
  246. else if (not AOnlyNum) and ((p^ = '-') or (p^ = ' ')) then
  247. Inc(p)
  248. else
  249. Exit;
  250. end;
  251. Result := i = 11; //中国手机号 11位
  252. end;
  253. function SizeUnitToInt(AUnit: Char): Int64;
  254. const
  255. Units: array [0 .. 6] of Char = ('b', 'k', 'm', 'g', 't', 'p', 'e');
  256. var
  257. I: Integer;
  258. LUnit: Char;
  259. begin
  260. Result := 1;
  261. case AUnit of
  262. 'A'..'Z':
  263. LUnit := Char(Word(AUnit) or $0020);
  264. else
  265. LUnit := AUnit;
  266. end;
  267. for I := Low(Units) to High(Units) do begin
  268. if (I > 0) then
  269. Result := Result * 1024;
  270. if LUnit = Units[I] then
  271. Exit;
  272. end;
  273. Result := 1;
  274. end;
  275. function SizeUnitToInt(AUnit: string): Int64;
  276. var
  277. LSize: string;
  278. begin
  279. Result := 1;
  280. LSize := Trim(AUnit);
  281. case Length(LSize) of
  282. 1,2: Result := SizeUnitToInt(PChar(AUnit)^);
  283. end;
  284. end;
  285. function SizeStrToInt(ASize: string; ADefault: Int64): Int64;
  286. var
  287. p: PChar;
  288. c: Char;
  289. s: string;
  290. begin
  291. Result := ADefault;
  292. if Length(ASize) = 0 then
  293. Exit;
  294. s := '';
  295. c := #0;
  296. p := PChar(ASize);
  297. while p^ <> #0 do
  298. case p^ of
  299. 'b', 'k', 'm', 'g', 't', 'p', 'e',
  300. 'B', 'K', 'M', 'G', 'T', 'P', 'E':
  301. begin
  302. if s = '' then
  303. Exit;
  304. if c <> #0 then
  305. Exit;
  306. c := p^;
  307. Inc(p);
  308. if (p^ = 'b') or (p^ = 'B') then
  309. Inc(p);
  310. end;
  311. '0' .. '9':
  312. begin
  313. if c <> #0 then
  314. Exit;
  315. s := s + p^;
  316. Inc(p);
  317. end;
  318. ',':
  319. begin
  320. if c <> #0 then
  321. Exit;
  322. Inc(p);
  323. end;
  324. ' ':
  325. Inc(p);
  326. else
  327. Exit;
  328. end;
  329. if s <> '' then
  330. Result := StrToInt64Def(s, Result) * SizeUnitToInt(c);
  331. end;
  332. function GetStrParamStr(P: PChar; var Param: String): PChar;
  333. function Extract(P: PChar; const Buffer: PChar; var Len: Integer): PChar;
  334. var
  335. InQuote: Boolean;
  336. begin
  337. Len := 0;
  338. InQuote := False;
  339. while (P^ <> #0) and ((P^ > ' ') or InQuote) do begin
  340. if P^ = '"' then
  341. InQuote := not InQuote
  342. else begin
  343. if Assigned(Buffer) then
  344. Buffer[Len] := P^;
  345. Inc(Len);
  346. end;
  347. Inc(P);
  348. end;
  349. Result := P;
  350. end;
  351. var
  352. Len: Integer;
  353. Buffer: String;
  354. begin
  355. Extract(P, nil, Len);
  356. SetString(Buffer, nil, Len);
  357. Result := Extract(P, @Buffer[1], Len);
  358. Param := Buffer;
  359. while (Result^ <> #0) and (Result^ <= ' ') do
  360. Inc(Result);
  361. end;
  362. function GetStrParamVal(Command: PChar; const Param, Default: String): String;
  363. var
  364. I, PCount: Integer;
  365. Z: String;
  366. begin
  367. PCount := StrParamCount(Command);
  368. for I := 1 to PCount do
  369. begin
  370. Z := StrParamStr(Command, I);
  371. if (StrLIComp(PChar(Z), PChar('/' + Param + '='), Length(Param) + 2) = 0)
  372. or (StrLIComp(PChar(Z), PChar('-' + Param + '='), Length(Param) + 2) = 0) then
  373. begin
  374. Delete(Z, 1, Length(Param) + 2);
  375. Result := Z;
  376. Exit;
  377. end;
  378. end;
  379. Result := Default;
  380. end;
  381. function GetStrParamVal(Command: string; const Param, Default: String): String;
  382. begin
  383. Result := GetStrParamVal(PChar(Command), Param, Default);
  384. end;
  385. function StrParamCount(Command: PChar): Integer;
  386. var
  387. P: PChar;
  388. S: String;
  389. begin
  390. P := GetStrParamStr(Command, S);
  391. Result := 0;
  392. while P^ <> #0 do begin
  393. Inc(Result);
  394. P := GetStrParamStr(P, S);
  395. end;
  396. end;
  397. function StrParamCount(Command: string): Integer;
  398. begin
  399. Result := StrParamCount(PChar(Command));
  400. end;
  401. function StrParamStr(Command: PChar; Index: Integer): string;
  402. { Returns the Indexth command line parameter, or an empty string if Index is
  403. out of range.
  404. Differences from Delphi's ParamStr:
  405. - No limits on parameter length
  406. - Doesn't ignore empty parameters ("")
  407. - Handles the empty argv[0] case like MSVC: if GetCommandLine() returns
  408. " a b" then NewParamStr(1) should return "a", not "b" }
  409. var
  410. Buffer: array[0..MAX_PATH-1] of Char;
  411. S: String;
  412. P: PChar;
  413. begin
  414. if Index <= 0 then begin
  415. Result := '';
  416. end
  417. else begin
  418. P := Command;
  419. while True do begin
  420. if P^ = #0 then begin
  421. S := '';
  422. Break;
  423. end;
  424. P := GetStrParamStr(P, S);
  425. if Index = 0 then Break;
  426. Dec(Index);
  427. end;
  428. Result := S;
  429. end;
  430. end;
  431. function StrParamStr(Command: string; Index: Integer): string;
  432. begin
  433. Result := StrParamStr(PChar(Command), Index);
  434. end;
  435. end.