Redirecting Print()
BlitzMax Forums/BlitzMax Programming/Redirecting Print()
| ||
| I want to capture Print commands so I can write the output to a log file, and to the console output. How can this be done?: The Print and Input commands can be redirected by setting the StandardIOStream Global to an alternative Stream Object. |
| ||
Ah, it's this easy:StandardIOStream =new TMyStream Type TMyStream Extends TStream Method WriteLine(s$) AddTextAreaText(Gadget_Console,s+"~n") AppLog(s) EndMethod EndType |
| ||
just overload print
EX.
Function Print(s$)
DebugLog("!!"+s)
End Function
|
| ||
| . |
| ||
| . |
| ||
SuperStrict
Import brl.standardio
Import brl.filesystem
Import brl.system
Type TLogPrintStream Extends TCStandardIO
Field file:String
Method New()
StandardIOStream = TTextStream.Create(Self, TTextStream.UTF8)
End Method
Method SetLogFile(url:String)
Local f:TStream = OpenFile(url)
If f
file = url
Else
CreateFile(url)
f = OpenFile(url)
If f
file = url
EndIf
EndIf
f.Seek(f.Size())
f.WriteLine("__________________")
f.WriteLine("|BEGIN LOG |")
f.WriteLine("|Date: " + CurrentDate() + "|")
f.WriteLine("|Time: " + CurrentTime()+" |")
f.WriteLine("|_________________|")
f.Close()
End Method
Method Write:Int(buf:Byte Ptr, count:Int)
If (file)
Local Log:TStream = OpenStream(file, 1, 1)
Log.Seek(Log.Size())
For Local n:Int = 0 Until Count
Log.WriteByte(buf[n])
Next
Log.Close()
End If
Return Super.Write(buf, count)
EndMethod
End Type
New TLogPrintStream.SetLogFile("log.txt")
|
| ||
Here's an even better method. This allows you to stack up custom print redirectors, and you can just mix and match as many as you want, without worrying about interference:New TConsoleStream Type TConsoleStream Extends TStream Field oldstream:TStream Method New() oldstream=StandardIOStream StandardIOStream=Self EndMethod Method WriteLine(s$) AddTextAreaText GADGET_console,s+"~n" oldstream.WriteLine(s) EndMethod EndType |
| ||
@Leadwerks: Just as a suggestion, wouldn't it be much better to do a real stream to handle console redirection?SuperStrict TConsoleStream.CreateConsoleStream(New TCStandardIO, TTextStream.UTF8, True) Print "Hello world!" Type TConsoleStream Extends TTextStream Field AdditionalRedirection(Text:String) 'Function pointer Function CreateConsoleStream:TConsoleStream(stream:TStream, encoding:Int, MakeStandardIoStream:Int = False) Local MyStream:TConsoleStream = New TConsoleStream MyStream._encoding = encoding MyStream.SetStream(stream) If MakeStandardIoStream = True Then StandardIOStream = MyStream EndIf Return MyStream End Function Method WriteLine(s:String) AddTextAreaText GADGET_console,s+"~n" If additionalRedirection <> Null Then AdditionalRedirection(s) Super.WriteLine(s) EndMethod EndType Just a suggestion. |
| ||
I'm very confused. Is this code correct?:Module leadwerks.logstream
Import brl.standardio
Import brl.filesystem
Strict
Global LogStreamEnabled:Int=True
Private
New TLogStream
Type TLogStream Extends TCStandardIO
Field oldstream:TStream
Field logstream:TStream
Field writestreamopenfailed:Int
Method New()
oldstream=StandardIOStream
StandardIOStream=Self
EndMethod
Method WriteLine(s:String)
If LogStreamEnabled
oldstream.WriteLine(s)
If Not logstream
If writestreamopenfailed Return
Local sarr:String[]
Local file:String
sarr=StripAll(AppFile).split(".")
file=sarr[0]+".log"
logstream=WriteFile(file)
If Not logstream
writestreamopenfailed=True
Return
EndIf
logstream.WriteLine(s)
EndIf
EndIf
EndMethod
EndType
Public |
| ||
| Yes, as long as those are really the only imports that this needs (I've tested as a non module). Also, I don't know how you can determine the order on wich the modules are imported on BlitzMax, so the StandardIoStream = self, could be overwritten by the Standadio global assigment (if that's executed later). I mean, is there any way to determine execution order of imports? Other that that, it looks ok to me, except that writting to the application folder usually involves virtualization on Vista or Win7. |
| ||
| @ziggy: Because imports have to be done before anything else, it will always have been set to the default stream before your code can do anything. EDIT: Ah.. I see what you mean. I guess the module containing the overriding stream would have to be imported after brl.standardio? |
| ||
| Yes, that's the point. Not sure if this can be ensured somehow. The best way to do it, I think, would be to make the StandardIOStream redirection as a function call called from the program using the TLogStream module. |