-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUFile.pas
More file actions
3528 lines (3089 loc) · 115 KB
/
UFile.pas
File metadata and controls
3528 lines (3089 loc) · 115 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// File and Disk Functions
// Date 20.04.20
{ TODO : Add TSortMode to GetFiles }
// 16.07.07 nk add in all functions better checks (set global FileError)
// 29.07.07 nk opt ff replace cNULL with cNUL (#0)
// 20.03.08 nk add GetFolderPath returns W2K, XP, and Vista folders
// 27.08.09 nk opt ff - set FileMode depending on read/write access
// 17.09.09 nk opt replace cDOT by MYDIR
// 11.12.09 nk opt try to close already opened file on I/O error 103
// 28.12.09 nk add public FileListing to make file names globally available
// 06.01.10 nk opt do not copy '.' (own folder) and '..' (parent folder) in CopyFiles
// 12.10.10 nk upd to Delphi XE (2011) Unicode UTF-16LE (Code site 1200)
// 12.12.10 nk add CopyFileAdv copies a file and numbers the copy if already exist
// 16.12.10 nk add GetFileFilter to fill combobox with file filters
// 27.12.10 nk add support for ANSI and Unicode UTF-16LE strings in ReplaceInFile
// 08.06.11 nk opt read/write files in ANSI or optional in UTF-8 Unicode compliant format
// 08.06.11 nk add replace WriteLn with WriteALine to write an Unicode string to an UTF-8 encoded file (e.g. XML)
// 08.06.11 nk add replace ReadLn with ReadALine to read an Unicode string from an UTF-8 encoded file (e.g. XML)
// 18.06.11 nk add compiler switch 'VERS400' for UTF-8 support instead of ISO-8859-1
// 27.01.12 nk add TSortMode for file and subdirectory sorting by name or timestamp (e.g. youngest first)
// 23.04.12 nk opt expand file names (with path) from MAXBYTE to MAX_PATH characters
// 23.09.12 nk add div. Application.ProcessMessages to not block application
// 20.02.14 nk upd to Delphi XE3 (VER240 Version 24)
// 17.05.15 nk opt in WriteToFile - assign code page CP_UTF8 and write BOM if file is UTF-8 encoded
// 08.04.16 nk add ReplaceInXML to replace strings in an UTF-8 encoded file
// 20.05.16 nk opt for 64-bit version
// 10.01.17 nk opt replace all cSTAR by ALLOF
// 10.08.18 nk add CopyDir, CopyFilesProgress, and OpenExplorer
// 15.08.18 nk opt DeleteDir - file errors are ignored and message dialog suppressed (set FOF_NOERRORUI)
// 19.11.19 nk add FindFileInSubdirs - check if at least one matching file is in subdirectories
// 20.04.20 nk opt undefine 'TCAD' to include UGraphic enabling GetImageCheckSum
{
see also System.IOUtils.TDirectory
File Attributes (defined in SysUtils)
===============
faReadOnly 1 write protected file
faHidden 2 hidden file
faSysFile 4 system file
faVolumeID 8 volume ID
faDirectory 16 directory
faArchive 32 archive file
faSymLink 64 system link
faAnyFile 71 any file
File Access Codes (defined in SysUtils)
=================
fmOpenRead $00
fmOpenWrite $01
fmOpenReadWrite $02
fmShareExclusive $10
fmShareDenyWrite $20
fmShareDenyRead $30
fmShareDenyNone $40
Directories
===========
CreateDir('C:\temp'); //einzelnes verzeichnis
if not ForceDirectories('c:\temp\test') then Error //ganzer pfad anlegen
NOTE: The FileCtrl version is deprecated, and the SysUtils version preferred
if not DeleteDir('C:\temp\test.txt') then Error
if FileCtrl.DirectoryExists('c:\temp') then... (with or without trailing '\') -> deprecated => use SysUtils.DirectoryExists
SetCurrentDirectory('C:\temp\'); or SetCurrentDir
GetDir(0, sString); //s aktuelle Arbeitsverzeichnis mit Laufwerksangabe
sPath := IncludeTrailingPathDelimiter(sPath);
sPath := ExcludeTrailingPathDelimiter(sPath);
RenameFile('C:\Alt\','C:\Neu\'); //Verzeichnis umbenennen
ProgramPath := ExtractFilePath(Application.ExeName);
Create a Directory : CreateDir('c:\path');
Remove a Directory : RemoveDir('c:\path') or RmDir('c:\path') => Folder must be empty!
Change a Directory : ChDir('c:\path')
Current Directory : GetCurrentDir
Check if a Directory exists : if DirectoryExists('c:\path') then ...
SHFileOperation - Copies, moves, renames, or deletes a file system object (see OperFileShell)
Files
=====
if FileExists('C:\Eigene Dateien\textdatei.txt') then ... => NO wildcards!
CopyFile(PChar(fileSource), PChar(fileDest), bFailIfExists);
RenameFile('c:\AlterName.exe', 'c:\NeuerName.exe'); - Returns True=ok, False=failed (e.g. no permission)
FileSetAttr('C:\io.sys', faReadOnly or faSysFile);
attribute := FileGetAttr('C:\io.sys');
FileSetAttr(FileName, FileGetAttr(FileName) xor faReadOnly); //remove flag - toggle all others!
FileSetAttr(FileName, FileGetAttr(FileName) or faReadOnly); //set flag
ShellExecute(Handle, 'open', 'c:\temp\test.doc', nil, nil, SW_SHOWNORMAL);
Label1.Caption := MinimizeName(FilName, Label1.Canvas, Label1.Width);
sFile := ChangeFileExt(sFile,'.rtf');
ExpandFileName - Liefert einen String, der einen vollständigen Pfad- und Dateinamen enthält.
ExtractFileDir - Liefert Laufwerksangabe und Verzeichnispfad des Dateinamens zurück (ohne "\")
ExtractFilePath - Liefert den vollständigen Pfad zu der angegebenen Datei (mit "\")
ExtractFileExt - Liefert die Dateinamenerweiterung mit Punkt zurück (.exe)
ExtractFileName - Liefert den angegebenen Dateinamen mit Erweiterung zurück (System.ini)
NewFileName := ChangeFileExt(FilName, ext); - Ersetzt Dateiendung .old = .new;
Rename a File: RenameFile('file1.txt', 'file2.xyz')
Delete a File: DeleteFile('c:\text.txt')
Move a File: MoveFile('C:\file1.txt', 'D:\file1.txt');
Copy a File: CopyFile(PChar(File1), PChar(File2), bFailIfExists)
Change a File's Extension: ChangeFileExt('test.txt', '.xls')
Check if a File exists: if FileExists('c:\filename.tst') then ... => NO wildcards!
CopyFile(
lpExistingFileName : PChar, // name of an existing file
lpNewFileName : PChar, // name of new file
bFailIfExists : Boolean); // if this parameter is TRUE and the new file specified by
//lpNewFileName already exists, the function fails.
//If this parameter is FALSE and the new file already exists,
//the function overwrites the existing file and succeeds.
bFailIfExists:
Specifies how this operation is to proceed if a file of the same name as
that specified by lpNewFileName already exists.
If this parameter is TRUE and the new file already exists, the function fails.
If this parameter is FALSE and the new file already exists,
the function overwrites the existing file and succeeds.
//extended file creation (see Microsoft MSDN for detailed description)
F := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil,
OPEN_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY or
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED or
FILE_FLAG_DELETE_ON_CLOSE or
FILE_FLAG_RANDOM_ACCESS, 0);
Result of 'GetFolderPath' under Windows Vista and later:
CSIDL_PERSONAL -> C:\Users\Daniel\Documents
CSIDL_MYPICTURES -> C:\Users\Daniel\Pictures
CSIDL_APPDATA -> C:\Users\Daniel\AppData\Roaming
CSIDL_LOCAL_APPDATA -> C:\Users\Daniel\AppData\Local
CSIDL_COMMON_APPDATA -> C:\ProgramData
CSIDL_WINDOWS -> C:\Windows
CSIDL_SYSTEM -> C:\Windows\system32
CSIDL_PROGRAM_FILES -> C:\Program Files
CSIDL_PROGRAM_FILES_COMMON -> C:\Program Files\Common Files
CSIDL_COMMON_DOCUMENTS -> C:\All Users\Documents
Result of 'GetFolderPath' under Windows XP
CSIDL_PERSONAL -> C:\Eigene Dateien
CSIDL_MYPICTURES -> C:\Eigene Dateien\Eigene Bilder
CSIDL_APPDATA -> C:\Dokumente und Einstellungen\Daniel\Anwendungsdaten
CSIDL_LOCAL_APPDATA -> C:\Dokumente und Einstellungen\Daniel\Lokale Einstellungen\Anwendungsdaten
CSIDL_COMMON_APPDATA -> C:\Dokumente und Einstellungen\All Users\Anwendungsdaten
CSIDL_WINDOWS -> C:\WINDOWS
CSIDL_SYSTEM -> C:\WINDOWS\system32
CSIDL_PROGRAM_FILES -> C:\Programme
CSIDL_PROGRAM_FILES_COMMON -> C:\Programme\Gemeinsame Dateien
}
unit UFile;
{$WARN SYMBOL_DEPRECATED OFF}
{$WARN SYMBOL_PLATFORM OFF}
interface
uses //UGraphic / 06.03.12 nk add Graphics
Windows, Forms, Classes, Math, SysUtils, StrUtils, StdCtrls, ComCtrls, ComObj,
Messages, Dialogs, Grids, Graphics, ImageHlp, ShellApi, ZLib, SHFolder,
{$IFNDEF TCAD} UGraphic, {$ENDIF} //52//20.04.20 nk add
UGlobal, USystem;
type //23.06.13 nk add fmNoFdel / 09.06.12 nk add fmTrim / 27.02.12 nk add fmNoTemp / 22.06.11 nk add fmLim3 / 26.04.08 nk add fmDirs, fmFiles
TFindMode = set of (fmCase, fmWord, fmSwap, fmAnsi, fmClear, fmExt, fmSort,
fmDirs, fmFiles, fmLim3, fmNoTemp, fmTrim, fmNoFdel);
TSortMode = (smNone, smName, smOldest, smYoungest); //27.01.12 nk add
TFileSize = (fsTotal, fsFree, fsUsed);
TFileOper = (foCopy, foDelete, foMove, foRename);
TDiskType = (dtRemovable, dtHarddisk, dtNetwork, dtLaserdisk, dtRamDisk, dtUnknown); //correspondes with DISK_ constants
//05.07.08 nk add feException
TFileError = (feNoError, feEmptyParameter, feInvalidParameter, feDriveNotReady,
feDirNotExist, feFileNotExist, feInternalError, feException);
TFileInfo = record
FileType: string;
CompanyName: string;
FileDescription: string;
FileVersion: string;
InternalName: string;
LegalCopyRight: string;
LegalTradeMarks: string;
OriginalFileName: string;
ProductName: string;
ProductVersion: string;
Comments: string;
SpecialBuildStr: string;
PrivateBuildStr: string;
FileFunction: string;
DebugBuild: Boolean;
PreRelease: Boolean;
SpecialBuild: Boolean;
PrivateBuild: Boolean;
Patched: Boolean;
InfoInferred: Boolean;
end;
const
PATHDEL = '\';
DRIVEDEL = ':'; //17.07.07 nk add
DISKDEL = ':\'; //25.07.10 nk add
NODRIVE = '-'; //24.07.10 nk add
FILEDEL = '_'; //23.06.13 nk add
EXTDEL = '.'; //V5//23.06.16 nk add
MYDIR = '.';
UPDIR = '..'; //52//19.11.19 nk add
CUTDIR = '...';
ALLOF = '*';
NONEOF = '!'; //29.07.12 nk add
ALLTYPES = '.*'; //06.03.10 nk add
OWNDIR = '.\';
PARENTDIR = '..\';
NETDIR = '\\';
COMMENT = '//'; //21.06.11 nk add
ALLFILES = '*.*';
STRINGDEL = ';'; //03.07.08 nk add standard string delimiter
UTF8_BOM = #$FEFF; //V5//17.05.15 nk add UTF-8 BOM (Byte Order Mark) = Byte sequenz 'EF BB BF'
FILE_ENCODING = ENCODING_UTF8; //18.06.11 nk add character set encoding (UTF-8/Unicode)
//20.03.08 nk del TMP_POST = '.tmp' (use TMP_END from UGlobal)
//06.09.08 nk opt ff - not defined in SHFolder.pas!?!
CSIDL_DESKTOP = $0000;
CSIDL_INTERNET = $0001;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005; //Version 6.0
CSIDL_FAVORITES = $0006;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000A;
CSIDL_STARTMENU = $000B;
CSIDL_MYDOCUMENTS = $000C;
CSIDL_MYMUSIC = $000D;
CSIDL_MYVIDEO = $000E; //Version 6.0
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011;
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
CSIDL_COMMON_STARTMENU = $0016;
CSIDL_COMMON_PROGRAMS = $0017;
CSIDL_COMMON_STARTUP = $0018;
CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
CSIDL_APPDATA = $001A; //Version 4.71
CSIDL_PRINTHOOD = $001B;
CSIDL_LOCAL_APPDATA = $001C; //Version 5.0
CSIDL_ALTSTARTUP = $001D;
CSIDL_COMMON_ALTSTARTUP = $001E;
CSIDL_COMMON_FAVORITES = $001F;
CSIDL_INTERNET_CACHE = $0020; //Version 4.72
CSIDL_COOKIES = $0021;
CSIDL_HISTORY = $0022;
CSIDL_COMMON_APPDATA = $0023; //Version 5.0
CSIDL_WINDOWS = $0024; //Version 5.0
CSIDL_SYSTEM = $0025; //Version 5.0
CSIDL_PROGRAM_FILES = $0026; //Version 5.0
CSIDL_MYPICTURES = $0027; //Version 5.0
CSIDL_PROFILE = $0028; //Version 5.0
CSIDL_SYSTEMX86 = $0029;
CSIDL_PROGRAM_FILESX86 = $002A;
CSIDL_PROGRAM_FILES_COMMON = $002B; //Version 5.0
CSIDL_COMMON_TEMPLATES = $002D;
CSIDL_COMMON_DOCUMENTS = $002E;
CSIDL_COMMON_ADMINTOOLS = $002F; //Version 5.0
CSIDL_ADMINTOOLS = $0030; //Version 5.0
CSIDL_CONNECTIONS = $0031;
CSIDL_COMMON_MUSIC = $0035; //Version 6.0
CSIDL_COMMON_PICTURES = $0036; //Version 6.0
CSIDL_COMMON_VIDEO = $0037; //Version 6.0
CSIDL_CDBURN_AREA = $003B; //Version 6.0
CSIDL_COMPUTERSNEARME = $003D;
SHGFP_TYPE_CURRENT = 0; //20.03.08 nk add
INVALID_FILE_CHARS = ['/', ':', '*', '<', '>', '|', #39, '?', '.', '\', '"'];
INVALID_PATH_CHARS = ['/', ':', '*', '<', '>', '|', #39, '?'];
DISK_REMOVE = 0; //10.07.09 nk add ff - correspondes with Ord(TDiskType)
DISK_HARD = 1;
DISK_NET = 2;
DISK_LASER = 3;
DISK_RAM = 4;
DISK_UNKNOWN = 5;
FORM_COPY = ' [%d].'; //12.12.10 nk add (file rename like 'Contrast [1].swl'
FORM_RTFCP = '\ansicpg'; //14.06.11 nk add
FORM_INFO = '\StringFileInfo\%.4x%.4x\%s'; //28.09.09 nk add ff
FILE_INFO = '\VarFileInfo\Translation';
DiskTypes: array[DISK_REMOVE..DISK_UNKNOWN] of string = //corresponds with TDiskType
('Removable', 'Harddisk', 'Network', 'Laserdisk', 'RamDisk', 'Unknown');
var
FileSubDir: Integer; //V5//23.06.16 nk add
FileMatching: Integer; //52//19.11.19 nk add
FileError: TFileError;
FileListing: TStringList; //28.12.09 nk add
function CheckDir(var DirName: string): Boolean;
function CheckFile(var FilName: string): Boolean;
function CopyDir(const FromDir, ToDir: string): Boolean; //09.08.18 nk add
function GetCheckSum(FilName: string): DWORD; //26.08.09 nk add
{$IFNDEF TCAD} //52//20.04.20 nk add
function GetImageCheckSum(FilName: string): Integer; //06.03.12 nk add
{$ENDIF}
function GetDrive: string;
function GetDriveFree: Char; //05.09.13 nk old=GetDiveFree / 24.07.10 nk add
function GetDriveLetter(VolumeLabel: string; NoFloppy: Boolean): Char; //25.07.10 nk add
function GetTempFile(Ext: string = TMP_END): string; //07.12.09 nk add
function GetWinDir: string;
function GetSysDir: string;
function GetTmpDir: string;
function GetAppDir: string;
function GetProgPath: string; //20.03.08 nk add ff
function GetDataPath: string;
function GetFontPath: string; //26.03.08 nk add
function GetDocuPath(Common: Boolean): string;
function GetFolderPath(CSIDL: Integer): string;
function GetDrives(DiskType: TDiskType; DriveList: TStrings): Integer;
function GetDiskType(DriveName: string): TDiskType;
function GetDiskSize(DriveName: string; SizeType: TFileSize): Int64;
function GetDiskName(DriveName: string): string;
function GetDiskCode(DriveName: string): string;
function GetFileSystem(DriveName: string): string;
function GetDirSize(DirName: string; WithSub: Boolean): Int64;
function GetParentDir(DirName: string): string;
function GetSubFolders(DirName: string; Ignore: string = ''): Boolean; //V5//10.01.17 nk add
function GetSubDirs(DirName: string; DirList: TStrings): Integer;
function GetFileSubDirs(DirName, FilName: string; DirList: TStrings; Sortby: TSortMode = smNone): Integer; //27.01.12 nk add Sortby
function GetFileTree(Tree: TTreeView; DirName: string; Node: TTreeNode; Mode: TFindMode; Excl: string = cEMPTY; Incl: string = cEMPTY): Integer; //V5//30.11.15 nk add Excl and Incl
function GetFileType(FilName: string): string;
function GetFileSize(FilName: string): Int64;
function GetFileDate(FilName, Format: string): string;
function GetFilePath(FilName, DirName: string): string;
function GetFileModify(FilName: string): TDateTime; //26.08.09 nk add
function GetFileTimes(FilName: string; var Times: array of TDateTime; Local: Boolean = True): Boolean; //26.08.09 nk add
function GetFileLines(FilName, Search: string; Mode: TFindMode; Encoding: string = FILE_ENCODING): Integer;
function GetFiles(FilName: string; FileList: TStrings; Mode: TFindMode): Integer;
function GetFileFilter(DirName: string; FileList: TStrings; FDel: TCharSet; FLen: Byte = 0; Ignore: string = cEMPTY): Integer; //01.08.12 nk add Ignore / 16.12.10 nk add
function GetFileCount(DirName, FilName: string; WithDir: Boolean = False): Integer; //22.09.12 nk add WithDir
function FindFileInSubdirs(DirName, FilName: string): Boolean; //52//19.11.19 nk add
function GetFileInfo(FilName: string): TFileInfo; //03.08.07 nk old=TFileName
function GetFileEncoding(FilName: string): string; //08.06.11 nk add
function GetLongFileName(FilName: string): string;
function GetProperFileName(FilName: string): string; //17.07.07 nk add
function GetFileGrid(FilName: string; Grid: TStringGrid; AltDel: string = ''; Encoding: string = FILE_ENCODING): Integer; //03.07.08 nk add
function SetFileGrid(FilName: string; Grid: TStringGrid; NoDups: Boolean; Encoding: string = FILE_ENCODING): Integer; //05.07.08 nk add
function SetFileDate(FilName: string; NewDate: TDateTime): Boolean; //07.09.09 nk add
function ExpandEnvPath(Path: string): string; //24.03.08 nk add
function ExtractFileBody(FilName: string): string; //17.07.07 nk add
function TrashFile(FilName: string): Boolean;
function DeleteDir(DirName: string; HideDialog: Boolean = True): Boolean; //06.02.19 nk opt/old=HideDialog: Boolean = False
function DeleteFiles(DirName, FilName: string; Size: Integer = 0): Integer;
function DeleteLines(FilName, Search: string; Mode: TFindMode; Encoding: string = FILE_ENCODING): Integer; //16.07.07 nk add
function CopyFileAdv(Source, Dest, FilName: string): string; //12.12.10 nk add
function CopyFiles(Source, Dest, FilName: string; Overwrite: Boolean = True; Attrib: Integer = 0): Integer; //16.12.09 nk add Overwrite and Attr
function CreateFolder(DirName: string; Clear: Boolean): Boolean;
function ReadFromFile(FilName: string; Line: Integer; Encoding: string = FILE_ENCODING): string;
function WriteToFile(FilName, Text: string; Encoding: string = FILE_ENCODING): Boolean; //xe//08.06.11 nk add encoding
function CountInFile(FilName, Search: string; Mode: TFindMode; Encoding: string = FILE_ENCODING): Integer; //27.01.08 nk add
function FindInFile(FilName, Search: string; Mode: TFindMode; Encoding: string = FILE_ENCODING): Integer;
function ReplaceInXML(FilName, Old, New: string; IsCase: Boolean): Boolean; //V5//08.04.16 nk add
function ReplaceInFile(FilName, Old, New: string; IsCase: Boolean; AsUnicode: Boolean = False): Boolean; //27.12.10 nk add AsUnicode
function ReplaceAllInFile(FilName, RepForm: string; RepList: TStringList): Boolean; //28.10.12 nk add
function WriteSignature(FilName: string; Signature: AnsiString): Integer; //xe//12.01.08 nk add ff
function ReadSignature(FilName: string): AnsiString; //xe//
function CopyFileProgress(Source, Dest: string; Progress: TProgressBar): Boolean;
function CopyFilesProgress(Source, Dest, FilName: string; Progress: TProgressBar): Integer; //10.08.18 nk add
function OperFileShell(Source, Dest: string; Oper: TFileOper; Head: string = cEMPTY): Boolean; //24.03.08 nk add Head
function OpenFileProperties(FilName: string): Boolean; //07.12.09 nk add
function LockFile(FilName, Locked: string): Boolean; //07.05.07 nk add
procedure ExtractResource(ResType: PChar; ResName, FilName: string); //xe//13.01.08 nk add ff
procedure CompressFile(FilIn, FilOut: string);
procedure DecompressFile(FilIn, FilOut: string);
procedure OpenExplorer(AFolder: string); //11.08.18 nk add
procedure ShowFileInfo(FilName: string; ListBox: TListBox);
procedure ReadALine(var ReadFile: Text; var ReadString: string; Encoding: string = FILE_ENCODING); //08.06.11 nk add
procedure WriteALine(var WriteFile: Text; WriteString: string; Encoding: string = FILE_ENCODING); //08.06.11 nk add
procedure SetFileEncoding(FilName: string; HeadLine: string = COMMENT; Encoding: string = FILE_ENCODING); //21.06.11 nk add
implementation
function CopyDir(const FromDir, ToDir: string): Boolean;
var //15.08.18 nk opt - call like: if CopyDir('D:\download', 'E:\') then...
fos: TSHFileOpStruct;
begin
ZeroMemory(@fos, SizeOf(fos));
with fos do begin
wFunc := FO_COPY;
fFlags := FOF_SILENT or FOF_NOCONFIRMMKDIR or FOF_FILESONLY or FOF_NOCONFIRMATION or FOF_NOERRORUI;
pFrom := PChar(FromDir + cNUL);
pTo := PChar(ToDir + cNUL);
end;
Result := (ShFileOperation(fos) = NERR_SUCCESS);
end;
function CheckDir(var DirName: string): Boolean;
// Try to normalize given directory name and check if it exists
// Input: DirName = directory or drive name to check
// like: 'A:', 'a:\', '.', '..', '\', '\\', 'C:\Temp', 'm:\net\..'
// where: 'a:'..'Z:' = drive letter
// '.' = current directory
// '..' = parent directory
// '\' = root directory
// '\\' = network direktory
// Output: DirName = normalized directory name with trailing slash
// like: 'C:\Temp\' or '\\server\D$\'
// Return: True if successful or False if failed
// Remark: Turn off critical errors to supress error dialog box
var //xe//
err: Word;
begin
Result := False;
FileError := feNoError;
err := NERR_SUCCESS;
DirName := StringReplace(DirName, cAPHOS, cEMPTY, [rfReplaceAll]);
DirName := StringReplace(DirName, cQUOTE, cEMPTY, [rfReplaceAll]);
DirName := Trim(DirName);
if DirName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
if DirName[1] = MYDIR then begin
DirName := StringReplace(DirName, PARENTDIR, GetParentDir(MYDIR), []);
DirName := StringReplace(DirName, OWNDIR, GetParentDir(cEMPTY), []);
end else
if DirName[1] = PATHDEL then begin
if Length(DirName) = 1 then begin
DirName := GetDrive; //root dir
end else begin
if Pos(NETDIR, DirName) = 1 then begin //network dir
DirName := IncludeTrailingPathDelimiter(DirName);
end else begin
DirName := StringReplace(DirName, PATHDEL, GetDrive, []);
end;
end;
end else
if CharInSet(DirName[1], SMALL_CHARS) then begin //xe//
if Pos(cCOLON, DirName) = 2 then begin
DirName[1] := Chr(Ord(DirName[1]) - ASCII_SPACE); //upper case
DirName := IncludeTrailingPathDelimiter(DirName);
end else begin
DirName := IncludeTrailingPathDelimiter(ExpandFileName(DirName));
end;
end else
if CharInSet(DirName[1], BIG_CHARS) then begin //xe//
if Pos(cCOLON, DirName) = 2 then begin
DirName := IncludeTrailingPathDelimiter(DirName);
end else begin
DirName := IncludeTrailingPathDelimiter(ExpandFileName(DirName));
end;
end else
if CharInSet(DirName[1], INVALID_PATH_CHARS) then begin //xe//
FileError := feInvalidParameter;
Exit;
end else begin
DirName := IncludeTrailingPathDelimiter(ExpandFileName(DirName));
end;
try //ignore critical errors
err := SetErrorMode(SEM_FailCriticalErrors);
if (DirName[1] <> PATHDEL) and (DiskSize(Ord(DirName[1]) - 64) = NONE)
then FileError := feDriveNotReady
else
if not DirectoryExists(DirName) then FileError := feDirNotExist;
finally
SetErrorMode(err); //restore original error mode
end;
Result := (FileError = feNoError);
end;
function CheckFile(var FilName: string): Boolean;
// Try to normalize given file name and check if it exists
// Input: FilName = file name to check (with optional path)
// like: 'drv32.dll', '..\Temp\*.txt', '\\neptun\net\bde.cfg'
// where: 'a:'..'Z:' = drive letter
// '*' = wild card ('*.*' is not allowed!)
// Output: FilName = normalized file name with full path
// like: 'C:\Win\Setup.exe' or '\\server\D$\*.ini'
// Return: True if successful or False if failed
// Remark: Turn off critical errors to supress error dialog box
var //xe//
err: Word;
begin
Result := False;
FileError := feNoError;
err := NERR_SUCCESS;
FilName := StringReplace(FilName, cAPHOS, cEMPTY, [rfReplaceAll]);
FilName := StringReplace(FilName, cQUOTE, cEMPTY, [rfReplaceAll]);
FilName := Trim(FilName);
if FilName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
if FilName[1] = MYDIR then begin
FilName := StringReplace(FilName, PARENTDIR, GetParentDir(MYDIR), []);
FilName := StringReplace(FilName, OWNDIR, GetParentDir(cEMPTY), []);
FilName := ExcludeTrailingPathDelimiter(FilName);
end else if
Pos(NETDIR, FilName) = 1 then begin
FilName := ExcludeTrailingPathDelimiter(FilName);
end else if
CharInSet(FilName[1], SMALL_CHARS) then begin //xe//
if Pos(cCOLON, FilName) = 2 then begin
FilName[1] := Chr(Ord(FilName[1]) - ASCII_SPACE); //upper case
FilName := ExcludeTrailingPathDelimiter(FilName);
end else begin
FilName := ExcludeTrailingPathDelimiter(ExpandFileName(FilName));
end;
end else if
CharInSet(FilName[1], BIG_CHARS) then begin //xe//
if Pos(cCOLON, FilName) = 2 then begin
FilName := ExcludeTrailingPathDelimiter(FilName);
end else begin
FilName := ExcludeTrailingPathDelimiter(ExpandFileName(FilName));
end;
end else if
CharInSet(FilName[1], INVALID_FILE_CHARS) then begin //xe//
FileError := feInvalidParameter;
Exit;
end else begin
FilName := ExcludeTrailingPathDelimiter(ExpandFileName(FilName));
end;
try //ignore critical errors
err := SetErrorMode(SEM_FailCriticalErrors);
if (FilName[1] <> PATHDEL) and (DiskSize(Ord(FilName[1]) - 64) = NONE)
then FileError := feDriveNotReady
else
if not FileExists(FilName) then FileError := feFileNotExist;
finally
SetErrorMode(err); //restore original error mode
end;
Result := (FileError = feNoError);
end;
function GetCheckSum(FilName: string): DWORD;
const //20.02.14 nk opt for XE3 - return checksum of FilName (with path)
BUFFLEN = 500; //in hex format like '5FA3DA9F'
var //CAUTION: FilName must exist!
p: Pointer;
fsize: DWORD;
bfile: file of DWORD; //01.07.11 nk old=f
buff: array [0..BUFFLEN] of DWORD;
begin
Result := NERR_SUCCESS;
FileError := feNoError;
FileMode := fmOpenRead or fmShareDenyNone;
try
AssignFile(bfile, FilName);
try
CloseFile(bfile); //11.12.09 nk opt ff - make sometimes I/O error 103 !?!
except
IOResult; //ignore if file was already closed
end;
Reset(bfile);
Seek(bfile, FileSize(bfile) div 2);
fsize := FileSize(bfile) - 1 - FilePos(bfile);
if fsize > BUFFLEN then fsize := BUFFLEN;
BlockRead(bfile, buff, fsize);
Close(bfile);
p := @buff;
{$IFDEF CPUX64} //20.02.14 nk opt for XE3
raise Exception.Create('GetCheckSum does not work on 64-bit systems!');
{$ELSE}
asm
xor eax, eax
xor ecx, ecx
mov edi , p
@again:
add eax, [edi + 4 * ecx]
inc ecx
cmp ecx, fsize
jl @again
mov @Result, eax
end;
{$ENDIF}
except
FileError := feException;
end;
end;
{$IFNDEF TCAD} //52//20.04.20 nk add
function GetImageCheckSum(FilName: string): Integer;
var //29.07.12 nk opt
i, j, cs: Integer;
pixel: Integer;
bmp: TBitmap;
line: PIntegerArray;
begin
cs := 0;
Result := NONE;
if not FileExists(FilName) then Exit;
bmp := LoadGraphicFile(FilName);
bmp.PixelFormat:= pf32bit;
for j := 0 to bmp.Height - 1 do begin
line := bmp.ScanLine[j];
for i := 0 to bmp.Width - 1 do begin
pixel := line^[i];
if ((pixel <> 15577344) and (pixel <> 15311104) and (pixel <> 3816255)
and (pixel <> 10526623) and (pixel <> 12303034) and (pixel <> 9013641)) then cs := cs + pixel;
end;
end;
Result := Abs(cs);
bmp.Free;
end;
{$ENDIF}
function GetDrives(DiskType: TDiskType; DriveList: TStrings): Integer;
// Return the number and a list of all drives of the requested type
// Input: DiskType = type of disk (dtRemovable..dtRamDisk) or
// dtUnknown for all types of disks
// Output: DriveList = strings in the format 'A:\'
// Return: number of drives found or 0 if failed or none
// Remark: DriveList will not be cleard - Drives will be append
var
num: Longword;
temp: array[0..MAX_PATH] of Char; //23.04.12 nk old=MAXBYTE
drive: PChar;
begin
Result := NERR_SUCCESS;
FileError := feNoError;
drive := temp;
num := GetLogicalDriveStrings(SizeOf(temp), temp);
if (num <= 0) or (num > SizeOf(temp)) then begin
FileError := feInternalError;
Exit;
end;
while drive^ <> cNUL do begin
if (DiskType = dtUnknown) or (GetDiskType(drive) = DiskType) then begin
DriveList.Append(drive);
Inc(Result);
end;
Inc(drive, 4);
end;
end;
function GetDiskType(DriveName: string): TDiskType;
// Return the type of a given disk or drive
// Input: DriveName = name of the drive in the format 'A:\'
// Output: None
// Return: Disk type (dtRemovable..dtRamDisk) or
// dtUnknown if failed or unknown
// Remark: Only the first character of the drive name is used
begin
Result := dtUnknown;
FileError := feNoError;
DriveName := Trim(DriveName);
if DriveName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
case GetDriveType(PChar(DriveName)) of
DRIVE_REMOVABLE: Result := dtRemovable;
DRIVE_FIXED : Result := dtHarddisk;
DRIVE_REMOTE : Result := dtNetwork;
DRIVE_CDROM : Result := dtLaserdisk;
DRIVE_RAMDISK : Result := dtRamDisk;
else
if LeftStr(DriveName, 2) = NETDIR then //09.07.09 nk add
Result := dtNetwork
else
FileError := feDriveNotReady;
end;
end;
function GetDiskSize(DriveName: string; SizeType: TFileSize): Int64;
// Return the requested size in bytes of the given disk or drive
// Input: DriveName = name of the drive in the format 'A:\'
// SizeType = fsTotal, fsFree, or fsUsed
// Output: None
// Return: Disk size in bytes or 0 if failed or not found
// Remark: Only the first character of the drive name is used
var
size: Int64;
free: Int64;
dir: string;
temp: array[0..4] of Char;
disk: PChar;
begin
Result := NERR_SUCCESS;
FileError := feNoError;
DriveName := Trim(DriveName);
if DriveName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
temp[0] := DriveName[1];
temp[1] := cCOLON;
temp[2] := PATHDEL;
temp[3] := cNUL;
disk := temp;
DriveName := string(disk);
if not CheckDir(DriveName) then Exit;
try
dir := GetCurrentDir;
if SetCurrentDir(DriveName) then begin
GetDiskFreeSpaceEx(disk, free, size, nil);
end else begin
FileError := feDriveNotReady;
Exit;
end;
SetCurrentDir(dir); //restore original directory
except
FileError := feException;
Exit;
end;
case SizeType of
fsTotal: Result := size;
fsFree: Result := free;
fsUsed: Result := size - free;
end;
end;
function GetDiskName(DriveName: string): string;
// Return the name of the given disk or drive
// Input: DriveName = name of the drive in the format 'A:\'
// Output: None
// Return: Disk name or empty if failed or not found
// Remark: Only the first character of the drive name is used
// This call may take a long time because of slower drives like floppy
var
nop: Cardinal;
buff: array[0..MAX_PATH] of Char;
temp: array[0..4] of Char;
disk: PChar;
begin
Result := cEMPTY;
FileError := feNoError;
DriveName := Trim(DriveName);
if DriveName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
buff := cEMPTY;
temp[0] := DriveName[1];
temp[1] := cCOLON;
temp[2] := PATHDEL;
temp[3] := cNUL;
disk := temp;
DriveName := string(disk);
if not CheckDir(DriveName) then Exit; //this call may take a long time for 'A:'
try //this call may take a long time for 'A:'
GetVolumeInformation(disk, buff, SizeOf(buff), nil, nop, nop, nil, 0);
finally
Result := StrPas(buff);
end;
end;
function GetDiskCode(DriveName: string): string;
// Return the serial number code of the given disk or drive
// Input: DriveName = name of the drive in the format 'A:\'
// Output: None
// Return: Disk serial number code in the format 'XXXXXXXX'
// (X = 0..F) or empty if failed or not found
// Remark: Only the first character of the drive name is used
// See also GetSerialNo in USystem
var
nop: Cardinal;
num: Cardinal;
temp: array[0..4] of Char;
disk: PChar;
begin
Result := cEMPTY;
FileError := feNoError;
DriveName := Trim(DriveName);
if DriveName = cEMPTY then begin
FileError := feEmptyParameter;
Exit;
end;
//03.08.07 nk del buff := cEMPTY;
temp[0] := DriveName[1];
temp[1] := cCOLON;
temp[2] := PATHDEL;
temp[3] := cNUL;
disk := temp;
DriveName := disk;
if not CheckDir(DriveName) then Exit;
try
//03.08.07 nk opt GetVolumeInformation(disk, buff, SizeOf(buff), @num, nop, nop, nil, 0);
GetVolumeInformation(disk, nil, MAX_PATH, @num, nop, nop, nil, 0);
finally
Result := Format(FORM_SERNO, [num]); //03.08.07 nk old='%8.8X';
end;
end;
function GetTempFile(Ext: string = TMP_END): string;
begin //07.12.09 nk add - create a unique temporary file name (w/o path)
Result := FormatDateTime(FORM_FILE_LONG, Now) + Ext;
end;
function GetDirSize(DirName: string; WithSub: Boolean): Int64;
// Return the total bytes of all files in the given directory
// Input: DirName = name of directory or drive
// like: 'A:\', 'C:\Temp' or '\\server\D$\'
// WithSub = search all subdirectories if True
// Output: None
// Return: Size of all files in the directory path in bytes
// or 0 if failed or directory not exists
// Remark:
var
drec: TSearchRec;
files: Integer;
begin
Result := NERR_SUCCESS;
FileError := feNoError;
if not CheckDir(DirName) then Exit;
files := FindFirst(DirName + ALLFILES, faAnyFile, drec);
while files = NERR_SUCCESS do begin
Inc(Result, drec.Size);
if (drec.Attr and faDirectory > NERR_SUCCESS) and (drec.Name[1] <> MYDIR) and (WithSub = True) then
Inc(Result, GetDirSize(DirName + drec.Name, True));
files := FindNext(drec);
end;
FindClose(drec);
end;
function GetDrive: string;
// Return the currently active drive
// Input: None
// Output: None
// Return: Current drive in the format 'C:\'
// Remark:
var
dir: string;
begin
FileError := feNoError;
GetDir(0, dir);
Result := LeftStr(dir, 3);
end;
function GetDriveFree: Char;
// Return the next free drive letter from 'Z' down to 'C'
// Input: None
// Output: None
// Return: Free drive in the format 'V' or NODRIVE if no letter is free
// Remark:
var
i: Integer;
drives: DWORD;
begin
Result := NODRIVE;
drives := GetLogicalDrives;
for i := 25 downto 2 do begin //do not test 'A' and 'B' even if they are free
if (drives and Round(IntPower(2, i))) = 0 then begin
Result := Char(ASCII + i);
Exit;
end;
end;
end;
function GetDriveLetter(VolumeLabel: string; NoFloppy: Boolean): Char;
// Return the drive letter of the given volume like 'C'
// Input: VolumeLabel - Name of volume like 'System'
// NoFloppy - Ignore slow drives 'A:' and 'B:' if True
// Output: None
// Return: Drive letter in the format 'C' or NODRIVE if volume not found
// Remark: This call may take a long time because slow drives like floppy
var
i, dnum: Integer;
disk: string;
devs: TStringList;
begin
Result := NODRIVE;
devs := TStringList.Create;
try
dnum := GetDrives(dtUnknown, devs);
for i := 0 to dnum - 1 do begin
disk := devs[i];
if NoFloppy then //ignore slow floppy disks
if (disk = 'A:\') or (disk = 'B:\') then Continue;
if VolumeLabel = GetDiskName(disk) then begin
Result := disk[1]; //return 1st char = drive letter like 'C'
Break;
end;
end;
finally
devs.Free;
end;
end;
function GetWinDir: string;
// Return the window directory path with trailing slash
// Input: None
// Output: None
// Return: Path of the windows folder like 'C:\Windows\'
// Remark:
var
buff: array[0..MAX_PATH] of Char;
begin
FileError := feNoError;
GetWindowsDirectory(buff, MAX_PATH);
Result := StrPas(buff);
Result := IncludeTrailingPathDelimiter(Result);
end;
function GetSysDir: string;
// Return the system directory path with trailing slash
// Input: None
// Output: None
// Return: Path of the system folder like 'C:\Windows\System32\'
// Remark:
var
buff: array[0..MAX_PATH] of Char;
begin
FileError := feNoError;
GetSystemDirectory(buff, MAX_PATH);
Result := StrPas(buff);
Result := IncludeTrailingPathDelimiter(Result);
end;
function GetTmpDir: string;
// Return the user temporary directory path with trailing slash
// Input: None
// Output: None
// Return: Path of the temporary folder like 'C:\Users\Benny\AppData\Local\Temp\'
// Remark:
var
buff: array[0..MAX_PATH] of Char;
begin
FileError := feNoError;
GetTempPath(MAX_PATH, buff);
Result := StrPas(buff);
Result := IncludeTrailingPathDelimiter(Result);
end;
function GetAppDir: string;
// Return the program directory path with trailing slash
// Input: None
// Output: None
// Return: Path of the application folder like 'C:\Programs\Test\'
// Remark:
begin
FileError := feNoError;
Result := ExtractFilePath(Application.ExeName);