Quick.Files.pas 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. { ***************************************************************************
  2. Copyright (c) 2016-2019 Kike Pérez
  3. Unit : Quick.Files
  4. Description : Files functions
  5. Author : Kike Pérez
  6. Version : 1.5
  7. Created : 09/03/2018
  8. Modified : 23/05/2019
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Files;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. {$IFDEF MSWINDOWS}
  28. Windows,
  29. {$ENDIF}
  30. {$IFDEF FPC}
  31. strutils,
  32. {$IFDEF LINUX}
  33. baseunix,
  34. {$ENDIF}
  35. {$ENDIF}
  36. {$IFDEF POSIX}
  37. Posix.Base,
  38. Posix.SysStat,
  39. Posix.Utime,
  40. {$ENDIF}
  41. DateUtils;
  42. {$IFDEF FPC}
  43. resourcestring
  44. SPathTooLong = 'The specified path is too long';
  45. SPathNotFound = 'The specified path was not found';
  46. SPathFormatNotSupported = 'The path format is not supported';
  47. SDirectoryNotEmpty = 'The specified directory is not empty';
  48. SDirectoryAlreadyExists = 'The specified directory already exists';
  49. SDirectoryInvalid = 'The specified directory name is invalid';
  50. SSourceDirIsDestDir = 'The source directory is the same as the destination directory';
  51. SSourceFileIsDestFile = 'The source file is the same as the destination file';
  52. SPathToFileNeeded = 'The path must specify a file';
  53. SSameRootDrive = 'The source and destination paths must contain the same root drive';
  54. SDriveNotFound = 'The drive cannot be found';
  55. SFileNotFound = 'The specified file was not found';
  56. SFileAlreadyExists = 'The specified file already exists';
  57. SInvalidCharsInPath = 'Invalid characters in path';
  58. SInvalidCharsInFileName = 'Invalid characters in file name';
  59. {$ENDIF}
  60. type
  61. {$IFNDEF FPC}
  62. TTextFileOperation = (tfOpenRead,tfOpenOverwrite,tfOpenAppend);
  63. TTextStreamFile = class
  64. private
  65. fReadStream : TStreamReader;
  66. fWriteStream : TStreamWriter;
  67. function GetEOF : Boolean;
  68. public
  69. constructor Create(const aFileName : string; aOpenMode : TTextFileOperation);
  70. destructor Destroy; override;
  71. function ReadLn: string; overload;
  72. function ReadLn(out Data: string): Boolean; overload;
  73. procedure WriteLn (const Data : string);
  74. procedure Close;
  75. property EOF: Boolean read GetEOF;
  76. end;
  77. {$IF Defined(MACOS) OR Defined(NEXTGEN) OR Defined(DELPHILINUX)}
  78. TFileTime = LongInt;
  79. {$ENDIF}
  80. {$ELSE}
  81. {$IFDEF LINUX}
  82. TFILETIME = LongInt;
  83. {$ENDIF}
  84. {$ENDIF}
  85. {$IFDEF FPC}
  86. EStreamError = class(Exception);
  87. EFileStreamError = class(EStreamError)
  88. constructor Create(ResStringRec: PResStringRec; const FileName: string);
  89. end;
  90. TPathPrefixType = (pptNoPrefix, pptExtended, pptExtendedUNC);
  91. { TPath }
  92. TPath = class
  93. private
  94. const
  95. FCCurrentDir: string = '.';
  96. FCParentDir: string = '..';
  97. FCExtendedPrefix: string = '\\?\';
  98. FCExtendedUNCPrefix: string = '\\?\UNC\';
  99. class procedure CheckPathLength(const Path: string; const MaxLength: Integer);
  100. public
  101. class function GetFileNameWithoutExtension(const FileName : string) : string;
  102. class function GetDirectoryName(const FileName : string) : string;
  103. class function GetExtension(const Path : string) : string;
  104. class function ChangeExtension(const Path, NewExtension : string) : string;
  105. class function GetFileName(const aPath : string) : string;
  106. class function EndsWithDelimiter(const aPath : string) : Boolean;
  107. class function Combine(const aPath1, aPath2 : string) : string;
  108. end;
  109. TDirectory = class
  110. public
  111. class function Exists(const Path: string; FollowLink: Boolean = True): Boolean;
  112. class function GetDirectories(const Path : string) : TArray<string>;
  113. end;
  114. TFile = class
  115. public
  116. class function Exists(const Path : string) : Boolean;
  117. class function IsInUse(const Path : string) : Boolean;
  118. class function GetSize(const Path : string) : Int64;
  119. class function Create(const Path: string; const BufferSize: Integer): TFileStream; overload;
  120. class function Create(const Path: string): TFileStream; overload;
  121. class function GetExtension(const Path : string) : string;
  122. class function GetCreationTime(const Path : string): TDateTime;
  123. class function GetLastAccessTime(const Path : string): TDateTime;
  124. class function GetLastWriteTime(const Path : string): TDateTime;
  125. class procedure SetCreationTime(const Path: string; const CreationTime: TDateTime);
  126. class procedure SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime);
  127. class procedure SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime);
  128. class function IsReadOnly(const Path : string) : Boolean;
  129. class function Delete(const Path : string) : Boolean;
  130. class function Move(const SourceFileName, DestFileName: string) : Boolean;
  131. end;
  132. TTextWriter = class
  133. public
  134. procedure Close; virtual; abstract;
  135. procedure Flush; virtual; abstract;
  136. procedure Write(Value: Boolean); overload; virtual; abstract;
  137. procedure Write(Value: Char); overload; virtual; abstract;
  138. procedure Write(Value: Double); overload; virtual; abstract;
  139. procedure Write(Value: Integer); overload; virtual; abstract;
  140. procedure Write(Value: Int64); overload; virtual; abstract;
  141. procedure Write(Value: TObject); overload; virtual; abstract;
  142. procedure Write(Value: Single); overload; virtual; abstract;
  143. procedure Write(const Value: string); overload; virtual; abstract;
  144. procedure Write(const aFormat: string; Args: array of const); overload; virtual; abstract;
  145. procedure WriteLine; overload; virtual; abstract;
  146. procedure WriteLine(Value: Boolean); overload; virtual; abstract;
  147. procedure WriteLine(Value: Char); overload; virtual; abstract;
  148. procedure WriteLine(Value: Double); overload; virtual; abstract;
  149. procedure WriteLine(Value: Integer); overload; virtual; abstract;
  150. procedure WriteLine(Value: Int64); overload; virtual; abstract;
  151. procedure WriteLine(Value: TObject); overload; virtual; abstract;
  152. procedure WriteLine(Value: Single); overload; virtual; abstract;
  153. procedure WriteLine(const Value: string); overload; virtual; abstract;
  154. procedure WriteLine(const aFormat: string; Args: array of const); overload; virtual; abstract;
  155. end;
  156. TStreamWriter = class(TTextWriter)
  157. private
  158. FStream: TStream;
  159. FEncoding: TEncoding;
  160. FNewLine: string;
  161. FAutoFlush: Boolean;
  162. FOwnsStream: Boolean;
  163. FBufferIndex: Integer;
  164. FBuffer: TBytes;
  165. procedure WriteBytes(Bytes: TBytes);
  166. public
  167. constructor Create(Stream: TStream); overload;
  168. constructor Create(Stream: TStream; Encoding: TEncoding; BufferSize: Integer = 4096); overload;
  169. constructor Create(const Filename: string; Append: Boolean = False); overload;
  170. constructor Create(const Filename: string; Append: Boolean; Encoding: TEncoding; BufferSize: Integer = 4096); overload;
  171. destructor Destroy; override;
  172. procedure Close; override;
  173. procedure Flush; override;
  174. procedure OwnStream; inline;
  175. procedure Write(Value: Boolean); override;
  176. procedure Write(Value: Char); override;
  177. procedure Write(Value: Double); override;
  178. procedure Write(Value: Integer); override;
  179. procedure Write(Value: Int64); override;
  180. procedure Write(Value: TObject); override;
  181. procedure Write(Value: Single); override;
  182. procedure Write(const Value: string); override;
  183. procedure Write(const aFormat: string; Args: array of const); override;
  184. procedure WriteLine; override;
  185. procedure WriteLine(Value: Boolean); override;
  186. procedure WriteLine(Value: Char); override;
  187. procedure WriteLine(Value: Double); override;
  188. procedure WriteLine(Value: Integer); override;
  189. procedure WriteLine(Value: Int64); override;
  190. procedure WriteLine(Value: TObject); override;
  191. procedure WriteLine(Value: Single); override;
  192. procedure WriteLine(const Value: string); override;
  193. procedure WriteLine(const aFormat: string; Args: array of const); override;
  194. property AutoFlush: Boolean read FAutoFlush write FAutoFlush;
  195. property NewLine: string read FNewLine write FNewLine;
  196. property Encoding: TEncoding read FEncoding;
  197. property BaseStream: TStream read FStream;
  198. end;
  199. {$ENDIF FPC}
  200. function CreateDummyFile(const aFilename : string; const aSize : Int64) : Boolean;
  201. procedure SplitFile(const aFileName : string; aSplitByteSize : Int64);
  202. procedure MergeFiles(const aFirstSplitFileName, aOutFileName : string); overload;
  203. procedure MergeFiles(aFilenames : array of string; const aOutFileName : string); overload;
  204. {$IFNDEF NEXTGEN}
  205. function IsFileInUse(const aFileName : string) : Boolean;
  206. {$ENDIF}
  207. procedure FileReplaceText(const aFileName, aSearchText, AReplaceText : string);
  208. {$IFNDEF NEXTGEN}
  209. function FileSearchText(const aFileName, SearchText: string; caseSensitive : Boolean): Longint;
  210. {$ENDIF}
  211. function GetCreationTime(const aFilename : string): TDateTime;
  212. function GetLastAccessTime(const aFileName: string): TDateTime;
  213. function GetLastWriteTime(const aFileName : string): TDateTime;
  214. {$IFDEF FPC}
  215. function FindDelimiter(const Delimiters, S: string; StartIdx: Integer = 1): Integer;
  216. {$ENDIF}
  217. function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
  218. procedure SetDateTimeInfo(const Path: string; const CreationTime, LastAccessTime, LastWriteTime: PDateTime; const UseLocalTimeZone: Boolean);
  219. implementation
  220. { TTextStreamFile }
  221. {$IFNDEF FPC}
  222. constructor TTextStreamFile.Create(const aFileName : string; aOpenMode : TTextFileOperation);
  223. var
  224. Append : Boolean;
  225. begin
  226. if aOpenMode = tfOpenRead then fReadStream := TStreamReader.Create(aFileName,True)
  227. else
  228. begin
  229. if aOpenMode = tfOpenAppend then Append := True
  230. else Append := False;
  231. fWriteStream := TStreamWriter.Create(aFileName,Append);
  232. end;
  233. end;
  234. destructor TTextStreamFile.Destroy;
  235. begin
  236. if Assigned(fReadStream) then fReadStream.Free;
  237. if Assigned(fWriteStream) then fWriteStream.Free;
  238. inherited Destroy;
  239. end;
  240. function TTextStreamFile.ReadLn(out Data: string): Boolean;
  241. begin
  242. Data := fReadStream.ReadLine;
  243. Result := Data <> '';
  244. end;
  245. function TTextStreamFile.ReadLn: string;
  246. begin
  247. Result := fReadStream.ReadLine;
  248. end;
  249. procedure TTextStreamFile.WriteLn (const Data : string);
  250. begin
  251. fWriteStream.WriteLine(Data);
  252. end;
  253. function TTextStreamFile.GetEOF : Boolean;
  254. begin
  255. Result := fReadStream.EndOfStream;
  256. end;
  257. procedure TTextStreamFile.Close;
  258. begin
  259. if Assigned(fReadStream) then fReadStream.Close;
  260. if Assigned(fWriteStream) then fWriteStream.Close;
  261. end;
  262. {$ENDIF NFPC}
  263. {$IFDEF FPC}
  264. { EFileStreamError }
  265. constructor EFileStreamError.Create(ResStringRec: PResStringRec;
  266. const FileName: string);
  267. begin
  268. {$IFNDEF LINUX}
  269. inherited CreateResFmt(ResStringRec, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]);
  270. {$ELSE}
  271. inherited CreateResFmt(ResStringRec, [ExpandFileName(FileName), SysErrorMessage(errno)]);
  272. {$ENDIF}
  273. end;
  274. { TPath }
  275. class function TPath.GetFileNameWithoutExtension(const FileName: string
  276. ): string;
  277. var
  278. fname : string;
  279. begin
  280. fname := ExtractFileName(FileName);
  281. Result := Copy(fname, 1, Length(fname) - Length(ExtractFileExt(fname)));
  282. end;
  283. class function TPath.ChangeExtension(const Path, NewExtension : string) : string;
  284. var
  285. dot : string;
  286. begin
  287. if NewExtension.Contains('.') then dot := ''
  288. else dot := '.';
  289. Result := TPath.GetFileNameWithoutExtension(Path) + dot + NewExtension;
  290. end;
  291. class function TPath.GetFileName(const aPath: string): string;
  292. begin
  293. Result := ExtractFileName(aPath);
  294. end;
  295. class function TPath.GetDirectoryName(const FileName : string) : string;
  296. begin
  297. Result := ExtractFileDir(Filename);
  298. end;
  299. class procedure TPath.CheckPathLength(const Path: string; const MaxLength: Integer);
  300. begin
  301. {$IFDEF MSWINDOWS}
  302. if (Length(Path) >= MaxLength) then
  303. {$ENDIF MSWINDOWS}
  304. {$IFDEF POSIX}
  305. if (Length(UTF8Encode(Path)) >= MaxLength) then
  306. {$ENDIF POSIX}
  307. raise EPathTooLongException.CreateRes(@SPathTooLong);
  308. end;
  309. class function TPath.GetExtension(const Path : string) : string;
  310. begin
  311. Result := ExtractFileExt(Path);
  312. end;
  313. class function TPath.EndsWithDelimiter(const aPath : string) : Boolean;
  314. var
  315. c : Char;
  316. begin
  317. if aPath = '' then Exit(False);
  318. c := aPath[High(aPath)];
  319. Result := (c = '\') or (c = '/');
  320. end;
  321. class function TPath.Combine(const aPath1, aPath2 : string) : string;
  322. var
  323. delim : string;
  324. begin
  325. delim := '';
  326. if aPath1.Contains('/') then delim := '/'
  327. else if aPath1.Contains('\') then delim := '\';
  328. if delim = '' then
  329. begin
  330. {$IFDEF LINUX}
  331. delim := '/';
  332. {$ELSE}
  333. delim := '\';
  334. {$ENDIF}
  335. end;
  336. if EndsWithDelimiter(aPath1) then
  337. begin
  338. if EndsWithDelimiter(aPath2) then Result := aPath1 + Copy(aPath2,2,aPath2.Length)
  339. else Result := aPath1 + aPath2;
  340. end
  341. else
  342. begin
  343. if EndsWithDelimiter(aPath2) then Result := aPath1 + aPath2
  344. else Result := aPath1 + delim + aPath2;
  345. end;
  346. end;
  347. { TDirectory }
  348. class function TDirectory.Exists(const Path: string; FollowLink: Boolean = True): Boolean;
  349. begin
  350. Result := DirectoryExists(Path);
  351. end;
  352. class function TDirectory.GetDirectories(const Path : string) : TArray<string>;
  353. var
  354. rec : TSearchRec;
  355. begin
  356. if FindFirst(TPath.Combine(Path,'*'),faAnyFile and faDirectory,rec) = 0 then
  357. repeat
  358. if ((rec.Attr and faDirectory) = faDirectory) and (rec.Name <> '.') and (rec.Name <> '..') then
  359. begin
  360. Result := Result + [rec.Name];
  361. end;
  362. until FindNext(rec) <> 0;
  363. SysUtils.FindClose(rec);
  364. end;
  365. { TFile }
  366. class function TFile.Exists(const Path : string) : Boolean;
  367. begin
  368. Result := FileExists(Path);
  369. end;
  370. class procedure TFile.SetCreationTime(const Path: string; const CreationTime: TDateTime);
  371. begin
  372. SetDateTimeInfo(Path,@CreationTime,nil,nil,True);
  373. end;
  374. class procedure TFile.SetLastAccessTime(const Path: string; const LastAccessTime: TDateTime);
  375. begin
  376. SetDateTimeInfo(Path,nil,@LastAccessTime,nil,True);
  377. end;
  378. class procedure TFile.SetLastWriteTime(const Path: string; const LastWriteTime: TDateTime);
  379. begin
  380. SetDateTimeInfo(Path,nil,nil,@LastWriteTime,True);
  381. end;
  382. class function TFile.IsReadOnly(const Path : string) : Boolean;
  383. begin
  384. Result := FileIsReadOnly(Path);
  385. end;
  386. class function TFile.Delete(const Path : string) : Boolean;
  387. begin
  388. Result := DeleteFile(PChar(Path));
  389. end;
  390. class function TFile.Move(const SourceFileName, DestFileName: string) : Boolean;
  391. begin
  392. {$IFNDEF LINUX}
  393. Result := MoveFile(PChar(SourceFileName),PChar(DestFileName));
  394. {$ELSE}
  395. Result := RenameFile(PChar(SourceFileName),PChar(DestFileName));
  396. {$ENDIF}
  397. end;
  398. {$IFNDEF NEXTGEN}
  399. class function TFile.IsInUse(const Path : string) : Boolean;
  400. begin
  401. Result := IsFileInUse(Path);
  402. end;
  403. {$ENDIF}
  404. class function TFile.GetSize(const Path : string) : Int64;
  405. var
  406. f : File of Byte;
  407. begin
  408. Assign(f,Path);
  409. try
  410. Reset (f);
  411. Result := FileSize(f);
  412. finally
  413. CloseFile(f);
  414. end;
  415. end;
  416. class function TFile.GetExtension(const Path : string) : string;
  417. begin
  418. Result := ExtractFileExt(Path);
  419. end;
  420. class function TFile.GetCreationTime(const Path : string) : TDateTime;
  421. begin
  422. Result := Quick.Files.GetCreationTime(Path);
  423. end;
  424. class function TFile.GetLastAccessTime(const Path : string) : TDateTime;
  425. begin
  426. Result := Quick.Files.GetLastAccessTime(Path);
  427. end;
  428. class function TFile.GetLastWriteTime(const Path : string) : TDateTime;
  429. begin
  430. Result := Quick.Files.GetLastWriteTime(Path);
  431. end;
  432. class function TFile.Create(const Path: string; const BufferSize: Integer): TFileStream;
  433. begin
  434. try
  435. Result := TFileStream.Create(Path,fmCreate);
  436. except
  437. on E: EFileStreamError do
  438. raise EInOutError.Create(E.Message);
  439. end;
  440. end;
  441. class function TFile.Create(const Path: string): TFileStream;
  442. begin
  443. Result := Create(Path, 0);
  444. end;
  445. { TStreamWriter }
  446. procedure TStreamWriter.Close;
  447. begin
  448. Flush;
  449. if FOwnsStream then
  450. FreeAndNil(FStream);
  451. end;
  452. constructor TStreamWriter.Create(Stream: TStream);
  453. begin
  454. inherited Create;
  455. FOwnsStream := False;
  456. FStream := Stream;
  457. FEncoding := TEncoding.UTF8;
  458. SetLength(FBuffer, 1024);
  459. FBufferIndex := 0;
  460. FNewLine := sLineBreak;
  461. FAutoFlush := True;
  462. end;
  463. constructor TStreamWriter.Create(Stream: TStream; Encoding: TEncoding; BufferSize: Integer);
  464. begin
  465. inherited Create;
  466. FOwnsStream := False;
  467. FStream := Stream;
  468. FEncoding := Encoding;
  469. if BufferSize >= 128 then
  470. SetLength(FBuffer, BufferSize)
  471. else
  472. SetLength(FBuffer, 128);
  473. FBufferIndex := 0;
  474. FNewLine := sLineBreak;
  475. FAutoFlush := True;
  476. if Stream.Position = 0 then
  477. WriteBytes(FEncoding.GetPreamble);
  478. end;
  479. constructor TStreamWriter.Create(const Filename: string; Append: Boolean);
  480. begin
  481. if (not FileExists(Filename)) or (not Append) then
  482. FStream := TFileStream.Create(Filename, fmCreate)
  483. else
  484. begin
  485. FStream := TFileStream.Create(Filename, fmOpenWrite);
  486. FStream.Seek(0, soEnd);
  487. end;
  488. Create(FStream);
  489. FOwnsStream := True;
  490. end;
  491. constructor TStreamWriter.Create(const Filename: string; Append: Boolean;
  492. Encoding: TEncoding; BufferSize: Integer);
  493. begin
  494. if (not FileExists(Filename)) or (not Append) then
  495. FStream := TFileStream.Create(Filename, fmCreate)
  496. else
  497. begin
  498. FStream := TFileStream.Create(Filename, fmOpenWrite);
  499. FStream.Seek(0, soEnd);
  500. end;
  501. Create(FStream, Encoding, BufferSize);
  502. FOwnsStream := True;
  503. end;
  504. destructor TStreamWriter.Destroy;
  505. begin
  506. Close;
  507. SetLength(FBuffer, 0);
  508. inherited;
  509. end;
  510. procedure TStreamWriter.Flush;
  511. begin
  512. if FBufferIndex = 0 then
  513. Exit;
  514. if FStream = nil then
  515. Exit;
  516. FStream.Write(FBuffer[0], FBufferIndex);
  517. FBufferIndex := 0;
  518. end;
  519. procedure TStreamWriter.OwnStream;
  520. begin
  521. FOwnsStream := True;
  522. end;
  523. procedure TStreamWriter.Write(const Value: string);
  524. begin
  525. WriteBytes(FEncoding.GetBytes(Value));
  526. end;
  527. procedure TStreamWriter.WriteBytes(Bytes: TBytes);
  528. var
  529. ByteIndex: Integer;
  530. WriteLen: Integer;
  531. begin
  532. ByteIndex := 0;
  533. while ByteIndex < Length(Bytes) do
  534. begin
  535. WriteLen := Length(Bytes) - ByteIndex;
  536. if WriteLen > Length(FBuffer) - FBufferIndex then
  537. WriteLen := Length(FBuffer) - FBufferIndex;
  538. Move(Bytes[ByteIndex], FBuffer[FBufferIndex], WriteLen);
  539. Inc(FBufferIndex, WriteLen);
  540. Inc(ByteIndex, WriteLen);
  541. if FBufferIndex >= Length(FBuffer) then
  542. Flush;
  543. end;
  544. if FAutoFlush then
  545. Flush;
  546. end;
  547. procedure TStreamWriter.Write(const aFormat: string; Args: array of const);
  548. begin
  549. WriteBytes(FEncoding.GetBytes(Format(aFormat, Args)));
  550. end;
  551. procedure TStreamWriter.Write(Value: Single);
  552. begin
  553. WriteBytes(FEncoding.GetBytes(FloatToStr(Value)));
  554. end;
  555. procedure TStreamWriter.Write(Value: Double);
  556. begin
  557. WriteBytes(FEncoding.GetBytes(FloatToStr(Value)));
  558. end;
  559. procedure TStreamWriter.Write(Value: Integer);
  560. begin
  561. WriteBytes(FEncoding.GetBytes(IntToStr(Value)));
  562. end;
  563. procedure TStreamWriter.Write(Value: Char);
  564. begin
  565. WriteBytes(FEncoding.GetBytes(Value));
  566. end;
  567. procedure TStreamWriter.Write(Value: TObject);
  568. begin
  569. WriteBytes(FEncoding.GetBytes(Value.ToString));
  570. end;
  571. procedure TStreamWriter.Write(Value: Int64);
  572. begin
  573. WriteBytes(FEncoding.GetBytes(IntToStr(Value)));
  574. end;
  575. procedure TStreamWriter.Write(Value: Boolean);
  576. begin
  577. WriteBytes(FEncoding.GetBytes(BoolToStr(Value, True)));
  578. end;
  579. procedure TStreamWriter.WriteLine(Value: Double);
  580. begin
  581. WriteBytes(FEncoding.GetBytes(FloatToStr(Value) + FNewLine));
  582. end;
  583. procedure TStreamWriter.WriteLine(Value: Integer);
  584. begin
  585. WriteBytes(FEncoding.GetBytes(IntToStr(Value) + FNewLine));
  586. end;
  587. procedure TStreamWriter.WriteLine;
  588. begin
  589. WriteBytes(FEncoding.GetBytes(FNewLine));
  590. end;
  591. procedure TStreamWriter.WriteLine(Value: Boolean);
  592. begin
  593. WriteBytes(FEncoding.GetBytes(BoolToStr(Value, True) + FNewLine));
  594. end;
  595. procedure TStreamWriter.WriteLine(Value: Char);
  596. begin
  597. WriteBytes(FEncoding.GetBytes(Value));
  598. WriteBytes(FEncoding.GetBytes(FNewLine));
  599. end;
  600. procedure TStreamWriter.WriteLine(Value: Int64);
  601. begin
  602. WriteBytes(FEncoding.GetBytes(IntToStr(Value) + FNewLine));
  603. end;
  604. procedure TStreamWriter.WriteLine(const aFormat: string; Args: array of const);
  605. begin
  606. WriteBytes(FEncoding.GetBytes(Format(aFormat, Args) + FNewLine));
  607. end;
  608. procedure TStreamWriter.WriteLine(Value: TObject);
  609. begin
  610. WriteBytes(FEncoding.GetBytes(Value.ToString + FNewLine));
  611. end;
  612. procedure TStreamWriter.WriteLine(Value: Single);
  613. begin
  614. WriteBytes(FEncoding.GetBytes(FloatToStr(Value) + FNewLine));
  615. end;
  616. procedure TStreamWriter.WriteLine(const Value: string);
  617. begin
  618. WriteBytes(FEncoding.GetBytes(Value + FNewLine));
  619. end;
  620. {$ENDIF FPC}
  621. {other functions}
  622. function CreateDummyFile(const aFilename : string; const aSize : Int64 ) : Boolean;
  623. var
  624. fs : TFileStream;
  625. i : Integer;
  626. buf : string;
  627. Begin
  628. Result := False;
  629. fs := TFileStream.Create(aFilename,fmCreate);
  630. buf := 'A';
  631. try
  632. fs.Seek(0, soBeginning);
  633. for i := 0 to aSize do fs.Write(buf[1], Length(buf));
  634. finally
  635. fs.Free;
  636. end;
  637. Result := FileExists(aFilename);
  638. End;
  639. procedure SplitFile(const aFileName : string; aSplitByteSize : Int64);
  640. var
  641. fs, ss: TFileStream;
  642. cnt : integer;
  643. splitname: string;
  644. begin
  645. fs := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite) ;
  646. try
  647. for cnt := 1 to Trunc(fs.Size / aSplitByteSize) + 1 do
  648. begin
  649. splitname := ChangeFileExt(aFileName, Format('%s%.3d', ['.',cnt])) ;
  650. ss := TFileStream.Create(splitname, fmCreate or fmShareExclusive) ;
  651. try
  652. if fs.Size - fs.Position < aSplitByteSize then
  653. aSplitByteSize := fs.Size - fs.Position;
  654. ss.CopyFrom(fs, aSplitByteSize) ;
  655. finally
  656. ss.Free;
  657. end;
  658. end;
  659. finally
  660. fs.Free;
  661. end;
  662. end;
  663. procedure MergeFiles(const aFirstSplitFileName, aOutFileName : string);
  664. var
  665. fs, ss: TFileStream;
  666. cnt: integer;
  667. splitfilename : string;
  668. begin
  669. cnt := 1;
  670. splitfilename := aFirstSplitFileName;
  671. fs := TFileStream.Create(aOutFileName, fmCreate or fmShareExclusive) ;
  672. try
  673. while FileExists(splitfilename) do
  674. begin
  675. ss := TFileStream.Create(splitfilename, fmOpenRead or fmShareDenyWrite) ;
  676. try
  677. fs.CopyFrom(ss, 0) ;
  678. finally
  679. ss.Free;
  680. end;
  681. Inc(cnt) ;
  682. splitfilename := ChangeFileExt(aFirstSplitFileName, Format('%s%.3d', ['.',cnt])) ;
  683. end;
  684. finally
  685. fs.Free;
  686. end;
  687. end;
  688. procedure MergeFiles(aFilenames : array of string; const aOutFileName : string);
  689. var
  690. filename : string;
  691. fs,
  692. ss : TFileStream;
  693. begin
  694. fs := TFileStream.Create(aOutFileName,fmCreate or fmShareExclusive) ;
  695. try
  696. for filename in aFilenames do
  697. begin
  698. if not FileExists(filename) then raise Exception.CreateFmt('Merge file %s not found!',[filename]);
  699. ss := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite) ;
  700. try
  701. fs.CopyFrom(ss,0);
  702. finally
  703. ss.Free;
  704. end;
  705. end;
  706. finally
  707. fs.Free;
  708. end;
  709. end;
  710. function IsFileInUse(const aFileName : string) : Boolean;
  711. {$IF NOT Defined(LINUX) AND NOT Defined(MACOS) AND NOT Defined(ANDROID)}
  712. var
  713. HFileRes: HFILE;
  714. begin
  715. Result := False;
  716. if not FileExists(aFileName) then Exit;
  717. try
  718. HFileRes := CreateFile(PChar(aFileName),
  719. GENERIC_READ or GENERIC_WRITE
  720. ,0
  721. ,nil
  722. ,OPEN_EXISTING
  723. ,FILE_ATTRIBUTE_NORMAL
  724. ,0);
  725. Result := (HFileRes = INVALID_HANDLE_VALUE);
  726. if not(Result) then begin
  727. CloseHandle(HFileRes);
  728. end;
  729. except
  730. Result := True;
  731. end;
  732. end;
  733. {$ELSE}
  734. var
  735. fs : TFileStream;
  736. begin
  737. try
  738. fs := TFileStream.Create(aFileName, fmOpenReadWrite, fmShareExclusive);
  739. Result := True;
  740. fs.Free;
  741. except
  742. Result := False;
  743. end;
  744. end;
  745. {$ENDIF}
  746. procedure FileReplaceText(const aFileName, aSearchText, AReplaceText : string);
  747. var
  748. fs: TFileStream;
  749. S: string;
  750. begin
  751. fs := TFileStream.Create(aFileName, fmOpenread or fmShareDenyNone);
  752. try
  753. SetLength(S, fs.Size);
  754. fs.ReadBuffer(S[1], fs.Size);
  755. finally
  756. fs.Free;
  757. end;
  758. S := StringReplace(S, aSearchText, AReplaceText, [rfReplaceAll, rfIgnoreCase]);
  759. fs := TFileStream.Create(aFileName, fmCreate);
  760. try
  761. fs.WriteBuffer(S[1], Length(S));
  762. finally
  763. fs.Free;
  764. end;
  765. end;
  766. {$IFNDEF NEXTGEN}
  767. function FileSearchText(const aFileName, SearchText: string; caseSensitive : Boolean): Longint;
  768. const
  769. BufferSize = $8001;
  770. var
  771. pBuf, pEnd, pScan, pPos: PAnsiChar;
  772. filesize: LongInt;
  773. bytesRemaining: LongInt;
  774. bytesToRead: Integer;
  775. F: file;
  776. SearchFor: PAnsiChar;
  777. oldMode: Word;
  778. begin
  779. Result := -1;
  780. if (Length(SearchText) = 0) or (Length(aFileName) = 0) then Exit;
  781. SearchFor := nil;
  782. pBuf := nil;
  783. AssignFile(F, aFileName);
  784. oldMode := FileMode;
  785. FileMode := 0;
  786. Reset(F, 1);
  787. FileMode := oldMode;
  788. try
  789. {$IFDEF FPC}
  790. SearchFor := PChar(StrAlloc(Length(SearchText) + 1));
  791. {$ELSE}
  792. {$IFDEF DELPHI2010_UP}
  793. SearchFor := PAnsiChar(StrAlloc(Length(SearchText) + 1));
  794. {$ELSE}
  795. SearchFor := StrAlloc(Length(SearchText) + 1);
  796. {$ENDIF}
  797. {$ENDIF FPC}
  798. StrPCopy(SearchFor, SearchText);
  799. {$IFDEF FPC}
  800. if not caseSensitive then UpperCase(SearchFor);
  801. {$ELSE}
  802. if not caseSensitive then AnsiUpperCase(SearchFor);
  803. {$ENDIF}
  804. GetMem(pBuf, BufferSize);
  805. filesize := System.Filesize(F);
  806. bytesRemaining := filesize;
  807. pPos := nil;
  808. while bytesRemaining > 0 do
  809. begin
  810. if bytesRemaining >= BufferSize then bytesToRead := Pred(BufferSize)
  811. else bytesToRead := bytesRemaining;
  812. BlockRead(F, pBuf^, bytesToRead, bytesToRead);
  813. pEnd := @pBuf[bytesToRead];
  814. pEnd^ := #0;
  815. pScan := pBuf;
  816. while pScan < pEnd do
  817. begin
  818. {$IFDEF FPC}
  819. if not caseSensitive then UpperCase(pScan);
  820. {$ELSE}
  821. if not caseSensitive then AnsiUpperCase(pScan);
  822. {$ENDIF}
  823. pPos := StrPos(pScan, SearchFor);
  824. if pPos <> nil then
  825. begin
  826. Result := FileSize - bytesRemaining +
  827. Longint(pPos) - Longint(pBuf);
  828. Break;
  829. end;
  830. pScan := StrEnd(pScan);
  831. Inc(pScan);
  832. end;
  833. if pPos <> nil then Break;
  834. bytesRemaining := bytesRemaining - bytesToRead;
  835. if bytesRemaining > 0 then
  836. begin
  837. Seek(F, FilePos(F) - Length(SearchText));
  838. bytesRemaining := bytesRemaining + Length(SearchText);
  839. end;
  840. end;
  841. finally
  842. CloseFile(F);
  843. if SearchFor <> nil then StrDispose(SearchFor);
  844. if pBuf <> nil then FreeMem(pBuf, BufferSize);
  845. end;
  846. end;
  847. {$ENDIF}
  848. {$IFDEF MSWINDOWS}
  849. function GetLastAccessTime(const aFileName: string): TDateTime;
  850. var
  851. ffd: TWin32FindData;
  852. dft: DWORD;
  853. lft: TFileTime;
  854. h: THandle;
  855. begin
  856. {$IFDEF FPC}
  857. h := FindFirstFile(PAnsiChar(aFileName), ffd);
  858. {$ELSE}
  859. h := FindFirstFile(PChar(aFileName), ffd);
  860. {$ENDIF}
  861. if (INVALID_HANDLE_VALUE <> h) then
  862. begin
  863. FindClose(h);
  864. FileTimeToLocalFileTime(ffd.ftLastAccessTime, lft);
  865. FileTimeToDosDateTime(lft, LongRec(dft).Hi, LongRec(dft).Lo);
  866. Result := FileDateToDateTime(dft);
  867. end;
  868. end;
  869. function GetCreationTime(const aFilename : string): TDateTime;
  870. var
  871. ffd: TWin32FindData;
  872. dft: DWORD;
  873. lft: TFileTime;
  874. h: THandle;
  875. begin
  876. {$IFDEF FPC}
  877. h := FindFirstFile(PAnsiChar(aFileName), ffd);
  878. {$ELSE}
  879. h := FindFirstFile(PChar(aFileName), ffd);
  880. {$ENDIF}
  881. if (INVALID_HANDLE_VALUE <> h) then
  882. begin
  883. FindClose(h);
  884. FileTimeToLocalFileTime(ffd.ftCreationTime, lft);
  885. FileTimeToDosDateTime(lft, LongRec(dft).Hi, LongRec(dft).Lo);
  886. Result := FileDateToDateTime(dft);
  887. end;
  888. end;
  889. function GetLastWriteTime(const aFileName : string): TDateTime;
  890. var
  891. ffd: TWin32FindData;
  892. dft: DWORD;
  893. lft: TFileTime;
  894. h: THandle;
  895. begin
  896. {$IFDEF FPC}
  897. h := FindFirstFile(PAnsiChar(aFileName), ffd);
  898. {$ELSE}
  899. h := FindFirstFile(PChar(aFileName), ffd);
  900. {$ENDIF}
  901. if (INVALID_HANDLE_VALUE <> h) then
  902. begin
  903. FindClose(h);
  904. FileTimeToLocalFileTime(ffd.ftLastWriteTime, lft);
  905. FileTimeToDosDateTime(lft, LongRec(dft).Hi, LongRec(dft).Lo);
  906. Result := FileDateToDateTime(dft);
  907. end;
  908. end;
  909. {$ELSE}
  910. {$IFDEF FPC} //FPC Linux
  911. function GetLastAccessTime(const aFileName: string): TDateTime;
  912. var
  913. info : stat;
  914. begin
  915. Result := 0;
  916. if fpstat(aFileName,info) <> 0 then
  917. begin
  918. Result := info.st_atime;
  919. end;
  920. end;
  921. function GetCreationTime(const aFilename : string): TDateTime;
  922. var
  923. info : stat;
  924. begin
  925. Result := 0;
  926. if fpstat(aFileName,info) <> 0 then
  927. begin
  928. Result := info.st_ctime;
  929. end;
  930. end;
  931. function GetLastWriteTime(const aFileName : string): TDateTime;
  932. var
  933. info : stat;
  934. begin
  935. Result := 0;
  936. if fpstat(aFileName,info) <> 0 then
  937. begin
  938. Result := info.st_mtime;
  939. end;
  940. end;
  941. {$ELSE} //Delphi Nextgen & Linux
  942. function GetLastAccessTime(const aFileName: string): TDateTime;
  943. var
  944. info : TDateTimeInfoRec;
  945. begin
  946. if FileGetDateTimeInfo(aFileName,info,True) then Result := info.LastAccessTime
  947. else Result := 0.0;
  948. end;
  949. function GetCreationTime(const aFilename : string): TDateTime;
  950. var
  951. info : TDateTimeInfoRec;
  952. begin
  953. if FileGetDateTimeInfo(aFileName,info,True) then Result := info.CreationTime
  954. else Result := 0.0;
  955. end;
  956. function GetLastWriteTime(const aFileName : string): TDateTime;
  957. var
  958. info : TDateTimeInfoRec;
  959. begin
  960. if FileGetDateTimeInfo(aFileName,info,True) then Result := info.TimeStamp
  961. else Result := 0.0;
  962. end;
  963. {$ENDIF}
  964. {$ENDIF}
  965. {$IFDEF FPC}
  966. function FindDelimiter(const Delimiters, S: string; StartIdx: Integer = 1): Integer;
  967. var
  968. Stop: Boolean;
  969. Len: Integer;
  970. begin
  971. Result := 0;
  972. Len := S.Length;
  973. Stop := False;
  974. while (not Stop) and (StartIdx <= Len) do
  975. if IsDelimiter(Delimiters, S, StartIdx) then
  976. begin
  977. Result := StartIdx;
  978. Stop := True;
  979. end
  980. else
  981. Inc(StartIdx);
  982. end;
  983. {$ENDIF}
  984. {$IFDEF MSWINDOWS}
  985. function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
  986. var
  987. LFileTime: TFileTime;
  988. SysTime: TSystemTime;
  989. begin
  990. Result.dwLowDateTime := 0;
  991. Result.dwLowDateTime := 0;
  992. DecodeDateTime(DateTime, SysTime.wYear, SysTime.wMonth, SysTime.wDay,
  993. SysTime.wHour, SysTime.wMinute, SysTime.wSecond, SysTime.wMilliseconds);
  994. if SystemTimeToFileTime(SysTime, LFileTime) then
  995. if UseLocalTimeZone then
  996. LocalFileTimeToFileTime(LFileTime, Result)
  997. else
  998. Result := LFileTime;
  999. end;
  1000. {$ENDIF}
  1001. {$If Defined(FPC) AND Defined(LINUX)}
  1002. function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
  1003. begin
  1004. { Use the time zone if necessary }
  1005. if not UseLocalTimeZone then
  1006. Result := DateTimeToFileDate(DateTime)
  1007. else
  1008. Result := DateTimeToFileDate(DateTime);
  1009. end;
  1010. {$ENDIF}
  1011. {$IFDEF POSIX}
  1012. function ConvertDateTimeToFileTime(const DateTime: TDateTime; const UseLocalTimeZone: Boolean): TFileTime;
  1013. begin
  1014. { Use the time zone if necessary }
  1015. if not UseLocalTimeZone then
  1016. Result := DateTimeToFileDate(TTimeZone.Local.ToLocalTime(DateTime))
  1017. else
  1018. Result := DateTimeToFileDate(DateTime);
  1019. end;
  1020. {$ENDIF}
  1021. procedure SetDateTimeInfo(const Path: string; const CreationTime, LastAccessTime, LastWriteTime: PDateTime; const UseLocalTimeZone: Boolean);
  1022. {$IFDEF MSWINDOWS}
  1023. var
  1024. LFileHnd: THandle;
  1025. LFileAttr: Cardinal;
  1026. LFileCreationTime: PFileTime;
  1027. LFileLastAccessTime: PFileTime;
  1028. LFileLastWriteTime: PFileTime;
  1029. begin
  1030. // establish what date-times must be set to the directory
  1031. LFileHnd := 0;
  1032. LFileCreationTime := nil;
  1033. LFileLastAccessTime := nil;
  1034. LFileLastWriteTime := nil;
  1035. try
  1036. try
  1037. if Assigned(CreationTime) then
  1038. begin
  1039. New(LFileCreationTime);
  1040. LFileCreationTime^ := ConvertDateTimeToFileTime(CreationTime^, UseLocalTimeZone);
  1041. end;
  1042. if Assigned(LastAccessTime) then
  1043. begin
  1044. New(LFileLastAccessTime);
  1045. LFileLastAccessTime^ := ConvertDateTimeToFileTime(LastAccessTime^, UseLocalTimeZone);
  1046. end;
  1047. if Assigned(LastWriteTime) then
  1048. begin
  1049. New(LFileLastWriteTime);
  1050. LFileLastWriteTime^ := ConvertDateTimeToFileTime(LastWriteTime^, UseLocalTimeZone);
  1051. end;
  1052. // determine if Path points to a directory or a file
  1053. SetLastError(ERROR_SUCCESS);
  1054. LFileAttr := FileGetAttr(Path);
  1055. if LFileAttr and faDirectory <> 0 then
  1056. LFileAttr := FILE_FLAG_BACKUP_SEMANTICS
  1057. else
  1058. LFileAttr := FILE_ATTRIBUTE_NORMAL;
  1059. // set the new date-times to the directory or file
  1060. LFileHnd := CreateFile(PChar(Path), GENERIC_WRITE, FILE_SHARE_WRITE, nil,
  1061. OPEN_EXISTING, LFileAttr, 0);
  1062. if LFileHnd <> INVALID_HANDLE_VALUE then
  1063. SetFileTime(LFileHnd, LFileCreationTime, LFileLastAccessTime, LFileLastWriteTime);
  1064. except
  1065. on E: EConvertError do
  1066. raise EArgumentOutOfRangeException.Create(E.Message);
  1067. end;
  1068. finally
  1069. CloseHandle(LFileHnd);
  1070. SetLastError(ERROR_SUCCESS);
  1071. Dispose(LFileCreationTime);
  1072. Dispose(LFileLastAccessTime);
  1073. Dispose(LFileLastWriteTime);
  1074. end;
  1075. end;
  1076. {$ENDIF}
  1077. {$IFDEF POSIX}
  1078. var
  1079. LFileName: Pointer;
  1080. LStatBuf: _stat;
  1081. LBuf: utimbuf;
  1082. ErrCode: Integer;
  1083. M: TMarshaller;
  1084. begin
  1085. { Do nothing if no date/time passed. Ignore CreationTime. Unixes do not support creation times for files. }
  1086. if (LastAccessTime = nil) and (LastWriteTime = nil) then
  1087. Exit;
  1088. LFileName := M.AsAnsi(Path, CP_UTF8).ToPointer;
  1089. { Obtain the file times. lstat may fail }
  1090. if ((LastAccessTime = nil) or (LastWriteTime = nil)) then
  1091. begin
  1092. ErrCode := stat(LFileName, LStatBuf);
  1093. { Fail if we can't access the file properly }
  1094. if ErrCode <> 0 then
  1095. Exit; // Fail here prematurely. Do not chnage file times if we failed to fetch the old ones.
  1096. end;
  1097. try
  1098. { Preserve of set the new value }
  1099. if LastAccessTime <> nil then
  1100. LBuf.actime := ConvertDateTimeToFileTime(LastAccessTime^, UseLocalTimeZone)
  1101. else
  1102. LBuf.actime := LStatBuf.st_atime;
  1103. { Preserve of set the new value }
  1104. if LastWriteTime <> nil then
  1105. LBuf.modtime := ConvertDateTimeToFileTime(LastWriteTime^, UseLocalTimeZone)
  1106. else
  1107. LBuf.modtime := LStatBuf.st_mtime;
  1108. { Call utime to set the file times }
  1109. utime(LFileName, LBuf);
  1110. except
  1111. on E: EConvertError do // May rise in ConvertDateTimeToFileTime
  1112. raise EArgumentOutOfRangeException.Create(E.Message);
  1113. end;
  1114. end;
  1115. {$ENDIF}
  1116. {$if Defined(FPC) AND Defined(LINUX)}
  1117. begin
  1118. end;
  1119. {$ENDIF}
  1120. end.