Comment savoir si une variable de type TextFile n’est pas utilisé suite à un AssignFile ?
Merci d’avance de vos lumières sur le sujet.
Comment savoir si une variable de type TextFile n’est pas utilisé suite à un AssignFile ?
Merci d’avance de vos lumières sur le sujet.
Quelle est le sens la question ?
AssignFile c'est pour indiquer le nom à une variable fichier File ou FileText, c'est un peu ancien comme façon de faire, cela ne fait que remplir un Record interne à Delphi pour la suite du traitement et rien de plus.
Un TFileStream, TStringStream ou TStringList sont aussi des façon de faire plus polyvalente et au cycle de vie plus facile à comprendre
Ce qui ouvre le fichier c'est Append, Reset ou Rewrite, c'est ces fonctions qui sont "terminées" via un CloseFile
C’est pour traiter un fichier log dans un thread dédié.
Je cherche juste à savoir si le fichier a déjà été ouvert une première fois et éviter une erreur si on cherche à l’ouvrir une 2ème fois alors qu’il est déjà ouvert !
Désolé si ma question a manqué de clarté
Bonjour,
Un TFileStream te permettrait d'empêcher le partage
https://flash-koti.developpez.com/ar...4-tfilestream/
de là si pas de permission => déjà en cours d'utilisation
C'est Append qui provoquera une erreur, soit par Exception soit par IOResult
Dans ce cas, j'utiliserais comme évoqué dans ma réponse précédente un TFileStream en fmOpenReadWrite + fmShareDenyWrite (gérer le fmCreate + fmShareDenyWrite si le fichier est absent, en général, j'utilise un fichier log par jour, voire un compteur par démarrage )
TFileStream se manipule en binaire, je te recommande d'écrire le BOM au début via UTF8.GetPreamble et continuer à log en encodant chaque chaine ensuite, avantage, cela te permet de manipuler des TBytes, idéal pour écrire dans un fichier
Si tu as un thread unique dédié au log, tu n'as pas de conflit possible au sein de ton process avec une variable privée de la classe hérité du TThread, je suppose que tu couples cela à un TThreadQueue pour une FIFO des logs.
Mais effectivement, si tu as plusieurs process qui partagent le fichier, là il faudra en libérer l'accès, donc la question de la durée de vie ne se pose plus, ouverture, ajout, fermeture à chaque fois.
Dans un programme, j'ai utilisée une Liste Chainee pour faire un FIFO de Thread d'écriture de log justement, du moins plutôt un fichier de compteur, je pouvais réécrire à certains endroits (un peu comme une table d'une DB en faite)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 var Server, Catalog, Schema, SQLText: string; DurationCommand, DurationQueryChanged: Int64; begin if Assigned(FLock) and Assigned(FSignal) then begin FLock.Acquire(); try if Peek(Server, Catalog, Schema, SQLText, DurationCommand, DurationQueryChanged) then begin if not FileExists(FFileName) or not FileWithHeader(HEADER) then if not CreateFileWithHeader(HEADER) then Exit; if AddSQLIntoFile(Server, Catalog, Schema, SQLText, DurationCommand, DurationQueryChanged) then Pop(); end; finally FLock.Release(); end; end; end; function CreateFileWithHeader(const AHeader: string): Boolean; var B: TBytes; begin try with TFileStream.Create(FFileName, fmCreate) do try B := TEncoding.UTF8.GetPreamble(); Write(B, Length(B)); B := TEncoding.UTF8.GetBytes(AHeader); Write(B, Length(B)); Result := True; finally Free(); end; except Result := False; end; end; function FileWithHeader(const AHeader: string): Boolean; var B, R: TBytes; begin try with TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite) do try B := TEncoding.UTF8.GetPreamble(); Seek(Length(B), soBeginning); B := TEncoding.UTF8.GetBytes(AHeader); SetLength(R, Length(B)); Result := (Read(R, Length(B)) = Length(B)) and CompareMem(@R[0], @B[0], Length(B)); finally Free(); end; except Result := False; end; end; function AddSQLIntoFile(const AServer: string; ACatalog: string; const ASchema: string; const ASQLText: string; const ADurationCommand, ADurationQueryChanged: Int64): Boolean; type ... var SQLTextClean: string; KeyText: string; KeyBinary: TBytes; Founds: TInt64DynArray; KeyFound, CountersFound: Boolean; TextCounters: TTextCounters; Counters: TCounters; C: Cardinal; begin ... with TFileStream.Create(FFileName, fmOpenReadWrite or fmShareDenyWrite) do try if not KeyFound then begin Seek(0, soEnd); Write(KeyBinary, Length(KeyBinary)); end; Write(TextCounters, SizeOf(TextCounters)); Result := True; finally Free(); end; except Result := False; end; end;
Problème pris à l'envers.
Juste utiliser TFile.AppendAllText protégé par un mutex (global pour un accès multi-session, par exemple app + service).
L'avantage de l'utilisation de TextFile est que Write est géré nativement par le compilateur et permet l'écriture de n'importe quel nombre d'arguments et de n'importe quel type sans conversion préalable.
Code : Sélectionner tout - Visualiser dans une fenêtre à part if TTextRec(f).Mode <> fmClosed then
Merci à vous pour vos solutions/suggestions.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager