Services Windows / Logs

Résolu
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 - 16 avril 2013 à 16:44
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 - 22 avril 2013 à 14:17
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

cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
22 avril 2013 à 12:35
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;

@+
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
17 avril 2013 à 17:27
Bonsoir,

regarde TFileStream

cantador
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
18 avril 2013 à 14:39
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
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
18 avril 2013 à 15:21
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
18 avril 2013 à 16:10
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
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
18 avril 2013 à 16:23
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;

@+
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
18 avril 2013 à 17:13
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
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
19 avril 2013 à 12:22
@simonpelloquin:
c'est cool..
mais on a encore le chargement complet
avec le LoadFromFile, ce que tu voulais éviter..


cantador
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
19 avril 2013 à 13:53
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...
@+
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
19 avril 2013 à 14:53
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
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
22 avril 2013 à 14:17
Ok, bien compris !
Merci !

Simon
Rejoignez-nous