I tried output to STDOUT every second by using NSTimer
.
I wrote the following code and saved it as sample.swift.
#!/usr/bin/swift
import AppKit
class Foo : NSObject {
override init() {
super.init()
NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "bar", userInfo: nil, repeats: true)
}
func bar() {
print("buz")
}
}
let h = Foo()
// Output successful
// while true {
// print("Foo!")
// }
NSRunLoop.mainRunLoop().run()
Then, I executed the following command and can see buz
.
okada@iyokan$ ./sample.swift
buz
buz
buz
buz
So, I executed the following command but I cannot see any buz
.
okada@iyokan$ ./sample.swift > sample.log # wait 5 seconds
okada@iyokan$ cat sample.log
okada@iyokan$
By the way, I tried while loop version (activated comment out the above code) then I could get buz
by two procedures.
Why I could not get any buz
?
Please teach me.
That is a "normal" behaviour of the stdio library. A file descriptor
can be "buffered", which means that the result of all printf()
and
other output operations goes to an internal buffer first. When that
buffer reaches a certain size (e.g. 8KB), its contents is written to the actual
file.
There are three modes: "unbuffered" (all output is written to the file
immediately), "line buffered" (output is collected until a newline
characters is printed),
and "fully buffered".
According to Is stdout line buffered, unbuffered or indeterminate by default?:
Unix convention is that stdin and stdout are line-buffered when associated with a terminal, and fully-buffered (aka block-buffered) otherwise.
This explains why you see the output of each print operation
immediately when the output goes to the terminal, but not when
output is redirected to a file.
With
print("buz")
fflush(stdout)
you can force the output to be written to the file immediately.
Alternatively, you can set standard output into line buffering mode
by calling
setlinebuf(stdout)
before anything is printed.