Что нового

[Данные, строки] Мониторинг логов большого размера (*.txt ~ 1,5 Mb)

kosjachok

Новичок
Сообщения
30
Репутация
3
Сделал такой монитор логов:
Код:
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>
#Include <File.au3>

;путь к любому текстовому логу
Local Const $sReceive = "C:\receive.log"

$Receive = FileOpen($sReceive, 0)
$hLinesR = _FileCountLines($sReceive)


$Form1 = GUICreate("Монитор логов", 640, 480, 100, 50, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS))
$ListR = GUICtrlCreateList("", 5, 30, 630, 450, BitXOR($LBS_NOSEL, $WS_VSCROLL,$WS_HSCROLL))
GUICtrlSetLimit(-1, 1300)
GUISetState(@SW_SHOW)

;доб существующих последних 10-ти строк лога в лист
$r = $hLinesR-10
While $r < $hLinesR
   $r = $r+1
   GUICtrlSetData ( $ListR, $r & '. '& FileReadLine ($Receive, $r) )
WEnd
_GUICtrlListBox_SetCaretIndex($ListR, $r)

AdlibRegister ( '_AddLine', 1000)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _AddLine()
   ;добавление новых строк в лист
			While $hLinesR < _FileCountLines($sReceive)
			   $hLinesR = $hLinesR + 1
			GUICtrlSetData ( $ListR, $hLinesR & '.-'& FileReadLine ( $Receive, $hLinesR) )
			_GUICtrlListBox_SetCaretIndex($ListR, $hLinesR)
			WEnd
EndFunc

Принцип работы - указываем лог (для примера можно взять лог любого ИМ), и в $ListR выводятся последние 10 строк + мониторятся новые строки, добавляющиеся в лог...
Вопрос: с маленькими логами работает нормально, с большими ~ 1,5 Mb, де > 20000 строк - $ListR очень медленно наполняется, и чем больше строк добавляется в лист - тем медленнее это происходит ... - Не поспевает за наполнением лога...
Как можно оптимизировать код для работы с большими логами?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
kosjachok
ты каждый раз читаешь весь файл. понятное дело, что чем больше файл тем дольше будет происходить последующие пополнения.
Вообще, для больших файлов FileReadLine с указанием номера строки - моветон. Запоминай размер файла при последнем чтении, и при следующем чтении - делай FileSetPos и читай уже с этого момента. Тем же FileReadLine.
 
Автор
K

kosjachok

Новичок
Сообщения
30
Репутация
3
Kaster
Как то так:?
Код:
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>
#Include <File.au3>

;путь к любому текстовому логу
Local Const $sReceive = "x:\Log\receive.log"

$Receive = FileOpen($sReceive, 0)
$hLinesR = _FileCountLines($sReceive)


$Form1 = GUICreate("Монитор логов", 640, 480, 100, 50, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS))
$ListR = GUICtrlCreateList("", 5, 30, 630, 450, BitXOR($LBS_NOSEL, $WS_VSCROLL,$WS_HSCROLL))
GUICtrlSetLimit(-1, 1300)
GUISetState(@SW_SHOW)

;доб существующих последних 10-ти строк лога в лист
$r = 0
$nFilePosR = 0
While $r < $hLinesR
   $r = $r+1
   FileSetPos($Receive, $nFilePosR, $FILE_BEGIN)
   GUICtrlSetData ( $ListR, $r & '. '& FileReadLine ($Receive, $r) )
   $nFilePosR = FileGetPos ($Receive)
WEnd
_GUICtrlListBox_SetCaretIndex($ListR, $r)

AdlibRegister ( '_AddLine', 1000)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _AddLine()
   ;добавление новых строк в ресив лог
			While $hLinesR < _FileCountLines($sReceive)
			   $hLinesR = $hLinesR + 1
			FileSetPos($Receive, $nFilePosR, $FILE_BEGIN)
			GUICtrlSetData ( $ListR, $hLinesR & '.-'& FileReadLine ( $Receive, $hLinesR) )
			$nFilePosR = FileGetPos ($Receive)
			_GUICtrlListBox_SetCaretIndex($ListR, $hLinesR)
			WEnd
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
kosjachok
У меня так достаточно быстро отрабатывает:
Код:
$sResume = ''
$iTimeout = TimerInit()
$hFile = FileOpen(@ScriptDir & '\Test.txt', 0)

$sText = FileRead($hFile)
$aText = StringSplit($sText, @LF)
For $i = $aText[0] - 9 To $aText[0]
	$sResume &= 'Строка № ' & $i & ' - ' & $aText[$i] & @LF
Next
$iTime = Round(TimerDiff($iTimeout) / 1000, 2) & " сек."
MsgBox(0, $iTime, $sResume)
Файл Test.txt у меня на 80000 строк размером 2,5 Мб.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
madmasles
тоже не панацея. не всякий файл можно поместить в память. но главный вопрос, зачем помещать в память 100%*(FileSize - Sizeof10Lines)/FileSize файла, если на практике используется только 100%*Sizeof10Lines/FileSize ?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
Kaster
Согласен. :smile:
 
Автор
K

kosjachok

Новичок
Сообщения
30
Репутация
3
Слепил всё до кучи, вот что получилось:
Код:
#Include <Array.au3>
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>
#Include <File.au3>

$sFile = 'd:\ххх.log'

$Form1 = GUICreate("Монитор логов", 640, 480, 100, 50, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS))
$ListR = GUICtrlCreateList("", 5, 30, 630, 450, BitXOR($LBS_NOSEL, $WS_VSCROLL,$WS_HSCROLL))
GUICtrlSetLimit(-1, 1300)
GUISetState(@SW_SHOW)

$aListR = _LogList($sFile, $ListR)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
	  
	 $aListR = _LogListUpd($sFile, $ListR, $aListR)
WEnd

Func _LogList($sFileX, $hListX )

$hFile = FileOpen($sFileX, 0)
$nSize = FileGetSize($sFileX)
If $nSize > 10000 Then 
   $nSize = $nSize-5000
Else
   $nSize = 0
EndIf
FileSetPos ( $hFile, $nSize, 0 )
$sText = FileRead($hFile)
$aText = StringSplit($sText, @LF)
$iS = _FileCountLines($sFileX) - $aText[0] -1
For $i = 2 To $aText[0]
   If $aText[$i] > "" Then 
	$iS += 1
   ; $sResume &= 'Строка № ' & $i & ' - ' & $aText[$i] & @LF
	GUICtrlSetData ( $hListX, 'Строка № ' & $iS & ' - ' & $aText[$i])
	EndIf
 Next
$nLines = _GUICtrlListBox_GetCount($hListX)
 _GUICtrlListBox_SetCaretIndex($hListX, $nLines)
 FileClose ($hFile)
 Dim $aVar[4]
 $aVar[0] = $nSize
 $aVar[1] = $nLines
 $aVar[2] = $iS
 Return ($aVar)
 EndFunc
 
 
Func _LogListUpd($sFileX, $hListX, $aVar)
$nSize2 = FileGetSize($sFileX)
$nSize = $aVar[0]
$nLines = $aVar[1]
$iS = $aVar[2]
	  If $nSize < $nSize2 Then
	  $hFile = FileOpen($sFileX, 0)
	  FileSetPos ( $hFile, $nSize, 0 )
	  $sText = FileRead($hFile)
	  $aText = StringSplit($sText, @LF)
		 For $i2 = 1 To $aText[0]
			If $aText[$i2] > "" Then 
			$iS += 1
			$nLines += 1 
			;$sResume &= 'Строка № ' & $i & ' - ' & $aText[$i] & @LF
			GUICtrlSetData ( $hListX, 'Строка № ' & $iS & ' - ' & $aText[$i2])
			_GUICtrlListBox_SetCaretIndex($hListX, $nLines)
			EndIf
		 Next
	  FileClose ($hFile)	  
	  $nSize = FileGetSize($sFileX)
	  EndIf	  
Dim $aVar2[4]
 $aVar2[0] = $nSize
 $aVar2[1] = $nLines
 $aVar2[2] = $iS
Return ($aVar2)
EndFunc

Что я могу сказать - теперь успевает обрабатывать 3 лога одновременно! :laugh: Всем спасибо!
 

damien2008

Осваивающий
Сообщения
157
Репутация
30
очень сильно извиняюсь за оффтоп, но все-таки.

текстовый документ из 6 строк некорректно обрабатывается
из
Код:
первая строка, повторится ведь? )
вторая строка, тоже ? О_о
третья строка, тоже ? О_о
ничего не понимаю
как оно работает?
)))
получаем следующее:

Autoit 3.3.8.1
 
Автор
K

kosjachok

Новичок
Сообщения
30
Репутация
3
Смени в первой функции
Код:
$aVar[0] = $nSize

на
Код:
$aVar[0] = FileGetSize($sFileX)


Там ещё первая строка теряется, у себя я эт давно уже все отладил и настроил,
но давно это было, сделал и забыл как грится...
 

damien2008

Осваивающий
Сообщения
157
Репутация
30
первая строка не тут случайно? : 8)
Код:
For $i = 2 To $aText[0]


Код:
For $i = 1 To $aText[0]
 
Верх