[R] Lenteurs avec FileReadLine inversé

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

[R] Lenteurs avec FileReadLine inversé

#1

Message par corrs78 »

Bonjour,
sans que je me l'explique l'operation de recherche d'une sous-chaine dans un fichier est 100x plus long si je commence par parcourir le fichier depuis la dernière ligne.

Concrètement :

si j’exécute ce script, il met un temps fou à parcourir le fichier.
Nota : sur un fichier de 1000 lignes, c'est seulement 2x plus long, environ 2scds pour parcourir le fichier de la ligne 1000 à 1
(1scd pour traiter dans le sens "normal" 1 à 1000)
par contre, j'ai l'impression que ce delta est exponentiel.
Sur mon fichier log de 50 000 lignes je parcours une journée de log en moins de 1scd si je commence par le debut du fichier, mais si je commence par la fin alors là je parcours le meme nombre de lignes en 30scds

Code : Tout sélectionner

#include<File.au3>
$mot_cle = "test"

 $Fichier_log = FileOpen("c:\ressources\logon.log", 0)
	If $Fichier_log = -1 Then
		MsgBox(0, "Erreur", "Impossible d'ouvrir le fichier logon.log")
		Exit
	EndIf

For $i= _FileCountLines("c:\ressources\logon.log") to 1 step -1
  $line = FileReadLine($Fichier_log, $i-1)
	consoleWrite($line & "   " &$i&@CRLF)
    If StringInStr($line, $mot_cle) Then
			ConsoleWrite($line)
	EndIf
Next
FileClose($Fichier_log)
j'ai bien tenté avec While > Wend, meme problème.

Help :)
Modifié en dernier par corrs78 le mar. 12 sept. 2017 16:56, modifié 1 fois.
Avatar du membre
TomAijerrie
Niveau 5
Niveau 5
Messages : 192
Enregistré le : lun. 02 juin 2014 09:55
Localisation : Lyon
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#2

Message par TomAijerrie »

Enregistre le nombre de ligne dans une variable, et utilise cette variable, ça évitera de rééxécuter la fonction _FileCountLines à chaque fois (50 000 fois environ)
Je ne suis pas sûr que ça vienne de là, mais c'est une piste.

J'ai souvent travaillé avec de gros fichers de logs, et ton script est très similaire aux miens. Sauf que j'utilise Do...Until ou While..Wend et que je sors une fois que j'ai la ligne qu'il me faut, ou une fois que la ligne que je veux lire n'existe pas (un petit "If @error then exitloop" apres le FileReadLine), comme ça, pas besoin de connaitre le nombre de ligne.
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#3

Message par corrs78 »

Merci de ta réponse. Je vais tester ça dès demain.

Précision(je ne l'ai pas affiché ici, pour simplifier le code) : l'objectif est d'afficher les 5 dernières lignes ou le mot clé est trouvé. Concrètement je veux afficher les 5derniers logs d'une machine.
Avatar du membre
orax
Modérateur
Modérateur
Messages : 1479
Enregistré le : lun. 23 mars 2009 04:50
Localisation : ::1
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#4

Message par orax »

_FileCountLines n'est exécuté qu'une seule fois (j'ai vérifié). C'est FileReadLine qui est long (dans ce cas particulier). Il y a aussi le ConsoleWrite qui affiche chaque ligne qui ralentit le script.

2 exemples à tester :

Code : Tout sélectionner

#include <File.au3>
#include <Array.au3>
$mot_cle = "test"

$t = TimerInit()
$aLines = FileReadToArray("c:\ressources\logon.log")

For $i = @extended - 1 To 0 Step -1
	If StringInStr($aLines[$i], $mot_cle) Then
		ConsoleWrite($i & " " & $aLines[$i] & @CRLF)
	EndIf
Next
ConsoleWrite(TimerDiff($t) & @CRLF)

$t = TimerInit()
$sFile = FileRead("c:\ressources\logon.log")
$a = StringRegExp($sFile, "test.*\R", 3)
ConsoleWrite(TimerDiff($t) & @CRLF)
_ArrayDisplay($a)
De petits détails peuvent faire toute la différence. — Quand la boule de neige commence à rouler… poussez-la. (Columbo)
Avatar du membre
TomAijerrie
Niveau 5
Niveau 5
Messages : 192
Enregistré le : lun. 02 juin 2014 09:55
Localisation : Lyon
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#5

Message par TomAijerrie »

Ces deux scripts fonctionnent bien pour des petits et moyens fichiers, mais perso, j'ai un PC en mousse, et quand j'ai testé avec un log plus gros que ma RAM libre, ça a crash...
Mais ce n'est pas moi qui va utiliser ce script, donc si son PC est plus costaux que le mien, et que ça marche, tant mieux.

Et je confirme que ConsoleWrite ralenti beaucoup. On pourrait plutôt ajouter les lignes dans une variable et tout afficher à la fin.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#6

Message par jchd »

Mieux vaudrait une approche plus efficace :

Code : Tout sélectionner

#include <File.au3>

Local $sFichier = "testcle.txt"	;"c:\ressources\logon.log"
Local $sMot_cle = "test"

Local $sText = FileRead($sFichier)
If @error Then
	MsgBox(0, "Erreur", "Impossible d'ouvrir le fichier logon.log")
Else
	Local $aLines = StringRegExp($sText, "(?m)(^.*\Q" & $sMot_cle & "\E.*$)", 3)
    If Not @error Then
		For $i = (UBound($aLines) >= 5 ? UBound($aLines) - 5 : 0) To UBound($aLines) - 1
			ConsoleWrite($aLines[$i] & @LF)
		Next
	EndIf
EndIf
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#7

Message par corrs78 »

jchd a écrit : mar. 12 sept. 2017 03:09 Mieux vaudrait une approche plus efficace :

Code : Tout sélectionner

#include <File.au3>

Local $sFichier = "testcle.txt"	;"c:\ressources\logon.log"
Local $sMot_cle = "test"

Local $sText = FileRead($sFichier)
If @error Then
	MsgBox(0, "Erreur", "Impossible d'ouvrir le fichier logon.log")
Else
	Local $aLines = StringRegExp($sText, "(?m)(^.*\Q" & $sMot_cle & "\E.*$)", 3)
    If Not @error Then
		For $i = (UBound($aLines) >= 5 ? UBound($aLines) - 5 : 0) To UBound($aLines) - 1
			ConsoleWrite($aLines[$i] & @LF)
		Next
	EndIf
EndIf
Merci jchd, cette méthode est en effet la plus efficace. Merci pour la RegExp, car je suis nul dans ce domaine :?
mon résultat est affiché instantanément dans un Richedit.
Par contre j'ai fait une condition "sans limite de résultats" , j'ai modifié le For de cette façon , ça ne fonctionne pas . j'ai raté un truc ?

Code : Tout sélectionner

For $i = UBound($aLines) To UBound($aLines) - 1
Merci
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#8

Message par jchd »

Dans ce cas :

Code : Tout sélectionner

For $i = 0 To UBound($aLines) - 1
et on obtient toutes les occurences.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

Re: [...] Lenteurs avec FileReadLine inversé

#9

Message par corrs78 »

Merci à tous. c'est parfait. :bisou:
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [R] Lenteurs avec FileReadLine inversé

#10

Message par jchd »

Seul (petit) bémol : il ne faut pas que le mot-clé contienne \E, sinon il faut une circonvolution supplémentaire. J'ai pensé que c'était peu probable pour un nom de machine.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

Re: [R] Lenteurs avec FileReadLine inversé

#11

Message par corrs78 »

Ne t'inquiète pas. Aucune chance dans mon log. Encore merci de ton aide.
Avatar du membre
corrs78
Niveau 5
Niveau 5
Messages : 160
Enregistré le : lun. 13 août 2007 17:38
Localisation : Yvelines
Status : Hors ligne

Re: [R] Lenteurs avec FileReadLine inversé

#12

Message par corrs78 »

jchd a écrit : mar. 12 sept. 2017 20:04 Seul (petit) bémol : il ne faut pas que le mot-clé contienne \E, sinon il faut une circonvolution supplémentaire. J'ai pensé que c'était peu probable pour un nom de machine.
Par contre je viens de me rendre un compte de deux choses
la casse est prise en compte. et vu que je cherche des noms propre, prénom, version d'OS c'est un problème.

il faudrait aussi que je puisse intégrer un délimiteur de texte. car si je cherche l'IP : "192.168.1.1" j'obtiens toutes les IP en 1***
par exemple ajouter des guillemets en debut et fin de chaine pour spécifier l'exclusivité de la recherche.

c'est possible d'intégrer ces paramètres dans ta RegExp


merci beaucoup.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2272
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [R] Lenteurs avec FileReadLine inversé

#13

Message par jchd »

Ah, une cible mouvante ! OK, mais je voudrais aussi que ça sorte ceci et pas cela... OK ça marche, mais sauf quand...

Une regexp est un programme et tout développement en spirale dérape en temps, énergie, bugs et complexité inutile.

Pour ignorer la casse :

Code : Tout sélectionner

StringRegExp($sText, "(?im)(^.*\Q" & $sMot_cle & "\E.*$)", 3)
L'option i en tête de regexp convient, du moins pour la plage ASCII A-Z <--> a-z. Si on veut que "Строка символов" ("Chaîne de caractères", en russe) soit reconnu égal à "СТРОКА СИМВОЛОВ" il faut ajouter (*UCP) en tête.

Code : Tout sélectionner

StringRegExp($sText, "(*UCP)(?im)(^.*\Q" & $sMot_cle & "\E.*$)", 3)
par exemple ajouter des guillemets en debut et fin de chaine pour spécifier l'exclusivité de la recherche.
Ce n'est pas une spécification, ça.
Ce qui compte c'est ce qu'il ne doit pas y avoir après "192.168.1.1" dans le log. Mais là ce n'est plus avec une variable motclé purement litérale qu'on peut faire ça.

Evalue l'ensemble de tes besoins et produit une spécification complète à partir de laquelle tu pourras être conseillé.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Répondre