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 printEX. 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. |