What is the difference between STDIN and $stdin in Ruby?
If $stdin
is reassigned, STDIN
is not affected. Likewise $stdin
is not affected when STDIN
is reassigned (which is perfectly possible (though pointless), but will produce a warning). However if neither variable has been reassigned, they both point to the same IO object, so calling reopen
¹ on one will affect the other.
All the built-in ruby methods use $<
(a.k.a. ARGF
) to read input. If ARGV
is empty, ARGF
reads from $stdin
, so if you reassign $stdin
, that will affect all built-in methods. If you reassign STDIN
it will have no effect unless some 3rd party method uses STDIN
.
In your own code you should use $stdin
to be consistent with the built-in methods².
¹ reopen
is a method which can redirect an IO object to another stream or file. However you can't use it to redirect an IO to a StringIO, so it does not eliminate all uses cases of reassigning $stdin
.
² You may of course also use $<
/ARGF
to be even more consistent with the built-in methods, but most of the time you don't want the ARGF
behavior if you're explicitly using the stdin stream.
Difference between `STDIN` and `$stdin`
From Ruby globals:
STDIN
The standard input. The default value for $stdin.
They are the same object by default.
[1] pry(main)> $stdin.object_id
=> 13338048
[2] pry(main)> STDIN.object_id
=> 13338048
[3] pry(main)> $stdin.object_id == STDIN.object_id
=> true
As @shivam commented, $stdin
is a global variable and it may be assigned to something different, while STDIN
is a constant.
Difference between $stdin and others gets.chomp
When invoking gets
without specifying the stream, we are invoking Kernel#gets and when stream is specified we are invoking IO#gets
I believe Kernel#gets
wraps around IO#gets
under the hood but before it needs to create an IO object, that IO object will be a concatenation of all command line arguments(ARGV) ( it will try to open every single one as file in positional order) and them read from it. If there are no elements left on ARGV it will then read from stdin.
That behavior can be tested with this simple snippet:
while gets
puts $_
end
When running ruby myscript.rb
without parameters it will read stdin, if parameters are specified it will try to open as files and read from it, it will works similarly to cat
command .
That stream could be tty, socket, file etc:
stream = File.open('/etc/passwd','r')
puts stream.gets
stream.close
A simple http client using sockets:
require 'socket'
s = TCPSocket.new 'icanhazip.com',80
s.puts <<~EOF
GET / HTTP/1.1
Host: icanhazip.com
EOF
while line = s.gets
puts line
end
s.close
More about Kernel#gets here
More about IO#gets
What's the difference between gets.chomp() vs. STDIN.gets.chomp()?
gets
will use Kernel#gets
, which first tries to read the contents of files passed in through ARGV
. If there are no files in ARGV
, it will use standard input instead (at which point it's the same as STDIN.gets
.
Note: As echristopherson pointed out, Kernel#gets
will actually fall back to $stdin
, not STDIN
. However, unless you assign $stdin
to a different input stream, it will be identical to STDIN
by default.
http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-gets
Is there any difference between $stdin.gets and gets?
gets
is Kernel#gets
, it first tries to read the contents of files passed in through ARGV
. If there are no files in ARGV
, it will use standard input instead (at which point it's the same as $stdin.gets
)
Ruby: What's the difference between STDIN.gets() and gets.chomp()?
Easiest way to do what you describe here is Integer(gets)
, since Integer()
ignores the trailing newline, so chomp
is unnecessary. There's also no need explicitly specify STDIN
as the receiver, as that's what Kernel#gets will do if there are no arguments to the script.
Difference between $stdout and STDOUT in Ruby
$stdout
is a global variable that represents the current standard output. STDOUT
is a constant representing standard output and is typically the default value of $stdout
.
With STDOUT
being a constant, you shouldn't re-define it, however, you can re-define $stdout
without errors/warnings (re-defining STDOUT
will raise a warning). for example, you can do:
$stdout = STDERR
Same goes for $stderr
and STDERR
So, to answer the other part of your question, use the global variables to redirect output, not the constants. Just be careful to change it back further on in your code, re-defining global variables can impact other parts of your application.
Ruby: What Does STDIN.gets mean?
If you run p STDIN.method(:gets)
you get #<Method: IO#gets>
. This means that the gets
method if defined in the IO module. Knowing that, you can then read the official documentation of gets
here:
http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets
The gets
method does not store its data in some default place, it returns it as the return value of the method. If that return value is being ignored, then the data is lost, but it could still be useful to call STDIN.gets
for its side effects: gets
will pause the execution of your thread and wait for input from the standard input. This would give the user a chance to review what the Ruby script has already done and terminate it early if the user wants to.
Related Topics
How to Remove Rvm (Ruby Version Manager) from My System
How to Use the Conditional Operator (? :) in Ruby
Ssl Error When Installing Rubygems, Unable to Pull Data from 'Https://Rubygems.Org/
Installed Ruby 1.9.3 With Rvm But Command Line Doesn't Show Ruby -V
What Is Ruby'S Double-Colon '::'
Why Is Division in Ruby Returning an Integer Instead of Decimal Value
Ruby Class Instance Variable Vs. Class Variable
How to Write a Switch Statement in Ruby
What Does the (Unary) * Operator Do in This Ruby Code
Why Doesn't Ruby Support I++ or I-- (Increment/Decrement Operators)
What's the Difference Between Equal, Eql, ===, and ==
When to Use 'Self.Foo' Instead of 'Foo' in Ruby Methods
Actioncontroller::Unknownformat
Why Are Gems Installed in a Directory With a Different Ruby Version Than I'M Running
Creating Matrix With 'Array.New(N, Array.New)'