How can I know if an IO is empty without reading it?
That's a purpose of IO::select method:
Updated example after question edited:
require 'open3'
select_timeout = Rational(1,10) # optional
Open3.popen3('ls /') do
|stdin, stdout, stderr, w_thread|
rdin, rdout, rderr = IO.select([stdin], [stdout], [stderr], select_timeout)
if rdin
p 'no data on standard input' unless rdin.member? stdin
p 'no data on standard output' unless rdout.member? stdout
p 'no data on standard error' unless rderr.member? stderr
else
p 'none of streams has data available'
end
retval = w_thread.value
end
# "no data on standard output"
# "no data on standard error"
Whereas only standard input contains data from spawned thread command ls /
How can I check if an InputStream is empty without reading from it?
I think you are looking for inputstream.available()
. It does not tell you whether its empty but it can give you an indication as to whether data is there to be read or not.
How to correctly check io.Reader for nil?
To check if an io.Reader
(or any other interface) value is nil
, you simply compare it to nil
.
Whether a non-nil
io.Reader
is a meaningful implementation, that's another question.
E.g. is this implementation meaningful?
type panicReader struct{}
func (panicReader) Read(p []byte) (int, error) {
panic("foo")
}
panicReader
certainly implements io.Reader
, but whenever you call its Read()
method, it will always panic.
There is bytes.Buffer
. A pointer to it implements io.Reader
. But calling Buffer.Read()
on a nil
*bytes.Buffer
pointer value will panic. But not because you can't call methods on nil
pointer receivers, but because the implementation of bytes.Buffer.Read()
tries to dereference the pointer receiver, and this dereference operation is what causes the panic:
// Excerpt from bytes.Buffer.Read implementation
func (b *Buffer) Read(p []byte) (n int, err error) {
b.lastRead = opInvalid
if b.empty() {
// ...
}
You can't make a general conclusion here (just yet). See this io.Reader
implementation:
type myBuffer struct{}
var count int
func (*myBuffer) Read(p []byte) (int, error) {
if len(p) > 0 {
count++
if count >= 10 {
return 0, io.EOF
}
p[0] = 'a'
return 1, nil
}
return 0, nil
}
*myBuffer
implements io.Reader
, and its Read()
method does not use the pointer receiver value. What does this mean? You can call Read()
on a nil
*myBuffer
value:
var data *myBuffer
request := &Request{
Body: data,
}
if request.Body != nil {
data, err := ioutil.ReadAll(request.Body)
fmt.Println(string(data), err)
}
This will output (try it on the Go Playground):
How to Know If an Io Is Empty Without Reading Ita <nil>
So the conclusion is this: usually types that have methods with pointer receiver require a non-nil
pointer because they use the pointed object (in case of bytes.Buffer
they use the fields of the pointed struct). To use such types (to have a meaningful implementation of implemented interfaces), you often need a non-nil
pointer value for the methods to "work". This–however–is not always a requirement as the above myBuffer
implementation shows. It's your job to always read the documentation of the used types and methods to avoid such misuses (e.g. trying to use a nil
*bytes.Buffer
).
See related question:
Hiding nil values, understanding why Go fails here
Go reflection with interface embedded in struct - how to detect "real" functions?
How to check potentially empty stdin without waiting for input?
The POSIX I/O functions that ultimately underlie Python's file objects have two different modes, blocking and non-blocking, controlled by a flag named O_NONBLOCK
. In particular, the read
function says:
When attempting to read a file … that … has no data currently available … If
O_NONBLOCK
is set, read() shall return -1 and set errno to[EAGAIN]
.
In Python, this flag is available in the os
module.
sys.stdin
is already open, so you can't just pass O_NONBLOCK
to the os.open
function, so… what do you do? Well, you actually might want to open /dev/tty
instead; it kind of depends on what you're actually doing. In that case, the answer is obvious. But let's assume that you don't. So, you want to change the flags of the already-open file. That's exactly what fcntl
is for. You use the F_GETFL
operation to read the current flags, or in the bit for O_NONBLOCK
, and F_SETFL
the result. You can remember the current flags for later if you want to restore things, of course.
In Python, the fcntl
function, and the operation constants, are available in the fcntl
module.
One last problem: sys.stdin
isn't a raw file object, it's a TextIOWrapper
that does Unicode decoding on top of a BufferedReader
, which itself adds buffering on top of a FileIO
. So, sys.stdin.read()
isn't directly calling the POSIX read
function. In order to do that, you need to use sys.stdin.buffer.raw
. And you may also need to do lots of careful flushing if you want to go back and forth between raw and normal input. (Note that this means you're giving up Unicode and instead getting a single-byte bytes
object, which could be, say, half of a UTF-8 character or a quarter of a terminal escape character. Hopefully you're expecting that.)
Now, what does FileIO.read
return when nothing is available? Well, it's an implementation of RawIOBase
, and RawIOBase.read
says:
If 0 bytes are returned, and size was not 0, this indicates end of file. If the object is in non-blocking mode and no bytes are available,
None
is returned.
In other words, you're going to get None
if nothing is available, b''
for EOF, or a single-byte bytes
for anything else.
So, putting it all together:
old_settings = termios.tcgetattr(fd)
old_flags = fcntl.fcntl(fd, fcntl.F_GETFL)
try:
tty.setraw(fd)
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags | os.O_NONBLOCK)
return sys.stdin.buffer.raw.read(1)
finally:
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags)
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
One last thing: Is there a way to tell if input is ready without reading it? Yes, but not portably. Depending on your platform, select
, poll
, epoll
, and/or kqueue
may be available and may work on regular files. read(0)
may be guaranteed to return b''
instead of None
. And so on. You can read your local man pages. But a simpler solution is the same thing C's stdio does: add a 1-byte-max buffer, and use it to implement your own read
and peek
or read
and unread
wrappers.
How to return a empty io.Reader?
In case of a non-nil
error return value, usually other parameters are left to the zero value of their type, which in case of io.Reader
(which is an interface type) should be nil
:
return nil, err
Callers are responsible to first always check the returned error, and only proceed to use other return values if the error is nil
. This is the general "rule". There may be exceptions of course, in which case you should document the deviant behavior.
Actually there's nothing wrong with providing other values along with non-nil
errors, and often it's useful. Typical example is the io.Reader.Read()
method, which documents how implementations should (must) work:
It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.
... When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read.
So even if Reader.Read()
returns a non-nil
error, it also reports how many bytes it was able to read successfully before the error was encountered, so you may process / use up to n
bytes from the slice.
How to check whether a file is empty or not
>>> import os
>>> os.stat("file").st_size == 0
True
How can I know text file is empty or not?(in C)
If the file was successfully open for read, as per fopen(filename, "r")
, you can verify if it is empty before any read operation this way:
int is_empty_file(FILE *fp) {
int c = getc(fp);
if (c == EOF)
return 1;
ungetc(c, fp);
return 0;
}
ungetc()
is guaranteed to work for at least one character. The above function will return 1
if the file is empty or if it cannot be read, due to an I/O error. You can tell which by testing ferr(fp)
or feof(fp)
.
If the file is a stream associated to a device or a terminal, the test code will block until at least one byte can be read, or end of file is signaled.
If the file is a regular file, you could also use a system specific API to determine the file size, such as stat
, lstat
, fstat
(on Posix systems).
Related Topics
Ruby/Rails - Active Record Db Migration to MySQL - Timestamp Type
Windows/Ruby Background Processing
Selenium Can't Find Fields with Type Number
Running Rake Task from Within War File
How to Specify Rvm Gemsets for Rails Gem Whenever
How to Get Data from Database in Ruby
How to Install Nokogiri on MAC Os Sierra 10.12
Is It a Bad Idea Do Divide the Models into Directories
Ruby Instance Method & Conditional Local Variable Assignment with Same Name
Differencebetween Def Func(Var) and Def Func=(Var)
Rails Form_For Never Invokes the Create Controller Action to Use Redirect_To
Ruby Webrick Http Authentication
Multiple Limit Condition in Mongodb
Rails Undefined Method 'Errors' for Nil:Nilclass in Simple_Form
Method Gives Activerecord::Relation Error
Are Spies an Appropriate Approach to See If Resque Methods Are Being Fired