An alternative to the Container approach is to "tail" the file in Lua. This is the kind of thing you will pretty much always want to do with something like a log file, that is appended sequentially from top to bottom, but you want to display in reverse chronological order from bottom to top. That's really how you always want to handle log files. They are always created by appending lines in chronological order, but you are always going to want to display them in reverse order. Newest to oldest...
I created a text file with 450,000 lines in it. It's something like 16 megabytes in size. So yeah, it's a GIANT log file...
Then:
Skin:
Code: Select all
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
MouseScrollDownAction=[!Refresh]
[Metadata]
Name=TailFile
Author=JSMorley & Brian
Information=Example of using Lua to "tail" a number of lines from a text file like a log or to-do list.||Simply set [Variables] to control which file is read, the number of lines, the width of the skin, and the interval in seconds.
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0
Version=July 4, 2016
[Variables]
FileToRead=#@#TailFile.log
LinesToTail=5
SkinWidth=350
SecondsBetweenRead=5
ChildPrefix=MeasureLine
[MeasureTail]
Measure=Script
ScriptFile=TailFile.lua
UpdateDivider=#SecondsBetweenRead#
[MeasureLine1]
Measure=String
UpdateDivider=-1
[MeasureLine2]
Measure=String
UpdateDivider=-1
[MeasureLine3]
Measure=String
UpdateDivider=-1
[MeasureLine4]
Measure=String
UpdateDivider=-1
[MeasureLine5]
Measure=String
UpdateDivider=-1
[StyleText]
X=5
Y=5R
W=(#SkinWidth# - 20)
H=16
FontSize=11
Padding=5,5,5,5
ClipString=1
AntiAlias=1
[StyleOdd]
FontColor=255,255,255,255
SolidColor=40,50,60,255
[StyleEven]
FontColor=230,230,230,255
SolidColor=60,70,80,255
[MeterBack]
Meter=Image
W=(#SkinWidth#)
H=([MeterLine#LinesToTail#:Y]+[MeterLine#LinesToTail#:H]+5)
SolidColor=10,20,30,255
DynamicVariables=1
LeftMouseUpAction=#FileToRead#
[MeterHeaderLeft]
Meter=String
X=5
Y=5
FontSize=11
FontColor=255,255,255,255
StringStyle=Bold
AntiAlias=1
Text=TailFile
ToolTipWidth=#SkinWidth#
ToolTipTitle=TailFile
ToolTipText=#FileToRead#
[MeterHeaderRight]
Meter=String
X=(#SkinWidth# - 10)
Y=0r
FontSize=11
FontColor=255,255,255,255
StringAlign=Right
AntiAlias=1
Text=Latest #LinesToTail# lines
[MeterLine1]
Meter=String
MeasureName=MeasureLine1
MeterStyle=StyleText | StyleOdd
Y=10R
[MeterLine2]
Meter=String
MeasureName=MeasureLine2
MeterStyle=StyleText | StyleEven
[MeterLine3]
Meter=String
MeasureName=MeasureLine3
MeterStyle=StyleText | StyleOdd
[MeterLine4]
Meter=String
MeasureName=MeasureLine4
MeterStyle=StyleText | StyleEven
[MeterLine5]
Meter=String
MeasureName=MeasureLine5
MeterStyle=StyleText | StyleOdd
Lua:
Code: Select all
function Initialize()
fileToRead = SKIN:GetVariable('FileToRead')
linesToTail = tonumber(SKIN:GetVariable('LinesToTail'))
childPrefix = SKIN:GetVariable('ChildPrefix')
end
function Update()
local inputFile = assert(io.open(fileToRead, 'r'))
local singleChar, lineText
local bytePosition = -1
local i = 1
repeat
inputFile:seek('end', bytePosition - 1)
singleChar = inputFile:read(1)
if singleChar == '\n' then
lineText = inputFile:read(-bytePosition)
if lineText then
lineText = string.gsub(lineText, '\r', '')
SKIN:Bang('!SetOption', childPrefix..i, 'String', string.match(lineText, '^(.-)\n'))
SKIN:Bang('!UpdateMeasure', childPrefix..i)
i = i + 1
bytePosition = bytePosition - 1
end
end
bytePosition = bytePosition - 1
until (i > linesToTail)
io.close(inputFile)
SKIN:Bang('!UpdateMeter', '*')
SKIN:Bang('!Redraw')
return 1
end
1.jpg
TailFile_1.0.rmskin
This is insanely fast, as it uses a binary "seek" to find the end of the file, then starts reading backwards from there based on linefeeds. This means it never has to read the boatloads of text starting from the top of the file. This is the approach I would always use to "tail" a file, and is particularly useful if you are reading something like a log file that might get really large.
This reads and builds the text strings using "bytes" and not "characters", so it won't be flummoxed by Unicode in Lua.
Reading the entire 450,000 lines of text in and putting the entirety of them in a meter that you constrain with a Container would just be hideously slow, memory wasteful, and inefficient in my view. Nothing particularly wrong with that approach for a small or moderately sized log file, but I really think that in all cases this makes more sense.
Note that this uses an approach where I populate individual String measures with the value, allowing you to use Substitute on them if desired to tweak things, and individual String meters to display them, allowing you to format the strings as desired and also use Inline Setting if you want to highlight key words like "error" and such if you need to. Nothing says you can't just append the strings in Lua however, and display the entire thing in one meter if that is what you want.
You do not have the required permissions to view the files attached to this post.