Services Windows / Logs [Résolu]

Signaler
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
-
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
-
Bonjour,

Pour un projet j'ai des programmes (tous les mêmes) qui écoutent sur un port (chacun le sien) l'arrivée de trames en provenance d'automates. Jusqu'à présent, ces programmes étaient en VCL, et j'affichais facilement ce que je voulais savoir sur leur état dans un stringgrid. Afin qu'ils tournent quand je ne suis pas logué sur la machine, pour alléger l'écran et retrouver plus facilement l'information, je bascule ces programmes en services windows avec un programme VCL "pour les contrôler tous"
La migration VCL vers Services s'est bien passée et le contrôleur VCL est prometteur. Ma question porte sur la transmission d'informations entre les services et ce contrôleur. Quelle serait d'après vous la meilleure façon de faire ?
Jusqu'à présent, sur le service, je fais un log sous forme de fichier texte. Je charge ce fichier dans un TStrings, j'insère une ligne en première position et je sauve le TStrings dans le fichier texte (Je n'ai rien trouvé dans la gestion des fichiers texte pour insérer une ligne en première ligne). Dans mon contrôleur, j'ai une analyse à faire sur les 10~15 premières lignes du log (j'ai besoin de garder quand même un historique que je veux pouvoir aussi consulter dans mon contrôleur si je veux plus de détails = chargement possible de tout le log). Je compte planifier des purges de ces fichiers régulièrement, mais je me demande si ça ne risque pas de poser des problèmes de perf sur des gros volumes (notamment sur le TStrings.LoadFromFile et SaveToFile). Est-ce que le fait d'ouvrir un fichier texte en lecture charge la totalité du fichier en mémoire ou bien est-ce que chaque ligne est chargé à sa lecture ?

Merci d'avance pour vos réponses.

Simon

11 réponses

Messages postés
250
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
2 décembre 2019
5
Rhaaa je me suis mal fait comprendre
Ben oui ShowMessage(S[1]^) marche pas c'est un string qu'on veut !
un exemple pour comprendre c'est plus ceci
S :='Test';
ShowMessage(PAnsiChar(S)^);// Retourne T
ShowMessage(PAnsiChar(S));// Retourne Test
ShowMessage(PAnsiChar(S)[0]);// Retourne T
ShowMessage(PAnsiChar(S)[1]);// Retourne e
ShowMessage(S[1]);// Retourne T

Tiens bon ben je reprend mon code à l'arrache avec TFileStream (Pas tester)
En gros ton fichier ne devrait pas dépasser 1024 Octets sauf...
Enfin ça te donne une idée par rapport à une structure ou un record etc...
var
  New     : TMemoryStream;
  S       : AnsiString;
  FStream : TFileStream;
  Buffer  : array [0..1023]of AnsiChar;//Je pars sur une taille de 1024 Octets
begin
New := TMemoryStream.Create;
try
  FStream := TFileStream.Create('C:\Test.txt', fmOpenRead);
  try
    FillChar(Buffer, Sizeof(Buffer), #0);//Je remplie le tableau par #0
    FStream.Read(Buffer, Length(Buffer));
    S := 'Test'+#13#10;//J'ajoute TestCRLF
    New.WriteBuffer(PChar(S)^, Length(S));
    if FStream.Size >= Length(Buffer) then
      New.WriteBuffer(Buffer[0], Length(Buffer)-Length(S))
    else
      New.WriteBuffer(Buffer[0], FStream.Size+Length(S));
    finally
      FStream.Free;
      New.SaveToFile('C:\Test.txt');
    end;
finally
  New.Free;
end;

@+
Messages postés
4715
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
12
Bonsoir,

regarde TFileStream

cantador
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
12
Salut cantador,

Je viens d'y jeter un coup d'oeil, mais je ne vois pas comment on peut insérer quelque chose en première ligne. Avec le "write", ça écrase le texte existant.
D'ailleurs, dans :
function Write(const Buffer; Count: Longint): Longint; override;

Pourquoi le "Buffer" n'est pas typé ?


Simon
Messages postés
4715
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
12
huumm..........Arggghhhh......heuuuuu.....

WriteBuffer, méthode (TStream)

Ecrit Count octets de Buffer dans le flux et avance la position en cours dans le flux de Count octets.

ça devrait permettre de remplacer la première ligne.

dis-moi..

sinon tu peux peut-être prendre le problème autrement :
les nouvelles lignes s'insèrent à la fin du fichier et là tu peux tenter le vieux WriteLn..

cantador
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
12
Pas mieux...
Il semble bien effectivement avancer la position en cours, mais il ne décale pas le texte et donc il m'écrase l'existant, or je cherche à insérer du texte.

Sinon pour ta suggestion, si je comprends bien, tu me propose de rester avec un textfile et d'ajouter à la fin (avec un append à l'ouverture). Pourquoi pas, si je n'arrive pas à ce que je voulais, je vais m'y résoudre. Ça m'embête un peu, parce que tu vois quand tu affiches un log de 10 pages comme ça, tu n'as pas directement les dernières infos (qui se trouvent du coup en bas de page). Il faut que tu molettes ou fasses un CTRL Fin pour atteindre les dernière lignes, et ça, ça fait perdre du temps et ça me gave... Sais-tu en revanche si le append charge tout le fichier en mémoire et donc perd du temps à le parcourir pour trouver la dernière position ? (L'aide de Delphi dit qu'il est ouvert en écriture seule...)

Simon
Messages postés
250
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
2 décembre 2019
5
Salut,
cantador a raison faut juste faire une gymnastique...
exemple un fichier qui supprime autant de caractères que de nouveaux
Dans ce fichier texte j'ai "TotoTiti" je rentre "Tata" à la sortie j'ai "TataToto"
L'exemple est très basique c'est pour la compréhension
var
    Source : TMemoryStream;
    New : TMemoryStream;
    S   : AnsiString;
begin
    Source := TMemoryStream.Create;
    New := TMemoryStream.Create;
    try
        Source.LoadFromFile('C:\Test.txt');
        S := 'Tata';
        New.WriteBuffer(S[1], Length(S));
        New.CopyFrom(Source,Source.Size-New.Size);
        New.SaveToFile('C:\Test.txt');
    finally
        Source.Free;
        New.Free;
    end;

@+
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
12
Ok yanb, merci
J'arrive effectivement à mes fins en faisant New.CopyFrom(Source,Source.Size); au lieu de New.CopyFrom(Source,Source.Size-New.Size);
On a bien une insertion.
Questions :
1) Pourquoi New.WriteBuffer(S[1], Length(S)); ? S[1] n'est pas le premier caractère de la chaine S ? Comment ça peut fonctionner ? (il me manque une notion ici... )
2) En terme de perf, c'est mieux qu'un TStrings.LoadFromFile ? (si oui pourquoi ? )

Simon
Messages postés
4715
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
12
@simonpelloquin:
c'est cool..
mais on a encore le chargement complet
avec le LoadFromFile, ce que tu voulais éviter..


cantador
Messages postés
250
Date d'inscription
lundi 27 octobre 2003
Statut
Membre
Dernière intervention
2 décembre 2019
5
Peut-être plus parlant pour toi c'est en fait un pointeur et pas le premier caractère
Mais je trouve plus simple cette ecriture
New.WriteBuffer(S[1], Length(S)); = New.WriteBuffer(PChar(S)^, Length(S));
En ce qui concerne les perf ben on charge le fichier en entier comme le dit cantador avec LoadFromFile
mais avec un TFileStream et ReadBuffer et une structure et un Buffer au poil ben ca devrait coller...
@+
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
12
ok, merci à vous 2 pour toutes ces précieuses informations. Je vais essayer de m'en servir intelligemment. Comme il faut que je charge au minimum mes services, je vais essayer de déporter le maximum de traitements dans le contrôleur. Peut être en créant plusieurs petits fichiers de log par rapport à la date et heure ou autre et en les fusionnant quand j'ai besoin de les consulter... On va bien voir.

Sinon yanb, ok pour le "pointeur" S[1]. Comme je suis un peu curieux, j'ai tenté un ShowMessage(S[1]^), qui d'après ton explication, devrait m'afficher S, non ? Eh bien, Delphi ne compile pas et me dit "Type pointeur requis"...

Simon
Messages postés
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
12
Ok, bien compris !
Merci !

Simon