I'm trying to read from a file, and because my more complex code doesn't work, I came back to basics to see whether it even reads properly.
My code:
MyParser.new(STDIN.read).run.lines.each do |line|
p line.chomp
end
I use
ruby program
(it's placed in a bin directory and I saved it without .rb )
Now program is waiting for me to write something. I type:
../examples/file.txt
and use CTRL + Z (I'm on Windows 10). It produces ^Z and I hit enter.
Now I have an error:
Invalid argument # rb_sysopen - ../examples/file.txt (Errno::EINVAL)
MyParser class and its whole logic works fine. I'll be grateful for any hints.
Without knowing, what your MyParser expect, it is hard to know, what you need.
But maybe this helps:
MyParser.new(STDIN.gets.strip).run.lines.each do |line|
p line.chomp
end
I would extend it by a message what you need:
puts "Please enter the filename"
STDOUT.flush
MyParser.new(STDIN.gets.strip).run.lines.each do |line|
p line.chomp
end
With STDOUT.flush the user gets the message, before STDIN.getswaits for a message.
In your case I would take a look on ARGV and call the program with:
ruby program ../examples/file.txt
Your program should then use:
MyParser.new(ARGV.first).run.lines.each do |line|
p line.chomp
end
Related
I have a beginners coding task, first step is my program "should prompt the user to enter a filename of a file that contains the following information:" There's already pre-made code to work on, a "music_player.rb" (where I have to write the code) and "albums.text" (which is the file I want to read from)
I know a_file = File.new("mydata.txt", "r") is to read from file. I'm trying to do:
file_name = gets()
a_file = File.new("#{file_name}" , "r") # (line 13)
I keep getting error
music_player_with_menu.rb:13:in `initialize': No such file or directory # rb_sysopen - albums.txt (Errno::ENOENT)
when I enter albums.txt. If I just remove gets and have File.new("albums.txt" , "r") it works. I'm not sure what I'm doing wrong.
Trying to read from mydata.txt\n is going to raise an exception unless the filename actually ends in \n, which is rarely the case. This is because you're using #gets, which includes the newline character(s) from the user pressing RETURN or ENTER.
When you read from STDIN, you will get a line-ending (e.g. \n on *nix, and \r\n on Windows). So, when you call #gets, you almost always need to call String#chomp on the result.
file_name = gets
#=> "foo\n"
file_name = gets.chomp
#=> "foo"
I'm having struggles understanding ruby. I wish to have a program in which a user can input a set of text and it come back with asterisks. So far I was able to do it via a .txt file. Can anyone explain where I went wrong? I am struggling with ruby a lot.
Image of outcome when I run it
print "Please enter any length of text:"
user_input = String(gets.chomp)
h = Hash.new
f = user_input
f.each_line { |line|
letters = line.split(//)
letters.each { |w|
if h.has_key?(w)
h[w] = h[w] + 1
else
h[w] = 1
end
}
}
# sort the hash by
h.sort{|a,b| a[1]<=>b[1]}.each { |elem|
puts "\"#{elem[0]}\": " + '*' * elem[1]
}
Error message I encountered
Undefined method `chomp' for nil:NilClass (NoMethodError)
In the script runner of Atom where you are currently running your Ruby program, you can not read from standard input using gets. It appears that the script-runner package can extend this to provide a real terminal to the script where you can then also use STDIN.
Alternatively, you could also run your program from a real console. For that, you have run it from a command line window, e.g. with ruby name_of_program.rb instead of starting it from Atom.
The gets method must be called alone. Try it in your second line:
user_input = gets.chomp
without String.
I hope it useful for you. :)
Your code is working as intended. You went wrong by running the code in your text editor instead of through the console. The Kernal#gets method requires user input, which would need to be mocked in order to run within your text-editor. Because your editor is returning nil instead of user input in string format, the chomp method is raising your NoMethodError.
Essentially your code is fine, but your are trying to run it in a limited environment. As a beginner, if your code requires user input, it's easier to test the code by running your ruby file through the console/terminal with ruby <filename.rb>.
I am using the Ruby processing library.
I would like to pipe output from a program into my code. For example, echo "hello" | rp5 run receiver.rb.
In a normal program, I know I can accomplish this with
while $stdin.gets
puts $_
puts "Receiving!"
end
And I know that in processing, the program loops through the draw function continuously. So I tried this code, but it did not work, since it freezes on the line puts $stdin.gets. So I know it must be a problem with the pipes not matching up, so I'm going to try using named pipes so that there is no confusion.
def setup
puts "setting up"
end
def draw
puts "drawing"
puts $stdin
puts $stdin.gets
puts "after gets"
while $stdin.gets
puts $_
puts "Receiving!"
end
puts "done drawing"
end
Any suggestion would be appreciated. I'm running Ubuntu 12.04.
Yep, the name pipes worked. Check out this example to get you started and make sure you have the latest version of JRuby loaded.
This is driving me crazy. Consider the following:
require 'open-uri'
#set up tempfile
extname = File.extname file_url
basename = File.basename(file_url, extname)
file = Tempfile.new([basename,extname])
#read form URI into tempfile
uri = URI.parse(file_url)
num_bytes_writen = file.write(uri.read)
puts "Wrote #{num_bytes_writen} bytes"
# Reading from my tempfile
puts "Opening: #{file.path} >>"
puts "#### BEGINING OF FILE ####"
puts File.open(file.path,'rb').read
puts "#### END OF FILE ####"
It looks like bytes get written, but when I try to open the file -- its empty. Whats up ?!
And to make it more weird -- everyting works in the Rails Console, but not when executed by a worker triggered by Resque.
Any ideas? Thanks guys
This is a problem of buffering. You need to flush the IO buffer to disk before trying to read it. Either file.close (if you've finished with it) or file.flush before doing the File.open for the read.
Update
I hadn't thought about this, but you don't need to reopen the temp file just to read it. It's already open for writing and reading, all you need to do is seek to the start of the file before reading. This way you don't have to do the flush (because you're actually reading from the buffer)...
# starting partway into your code...
num_bytes_written = file.write(uri.read)
puts "Wrote #{num_bytes_written} bytes"
puts "No need to open #{file.path} >>"
puts "### BEGINNING OF FILE ###"
file.rewind # set the cursor to the start of the buffer
puts file.read # cursor is back at the end of the buffer now
puts "### END OF FILE ###"
Another Update
After a comment from #carp I have adjusted the code above to use rewind instead of seek 0 because it also resets lineno to 0 (and not having that done, if you were using lineno would be very confusing). Also actually it's a more expressive method name.
Always close your files. Try using this style in your code, to avoid such mistakes:
File.open(myfile,"w") {|f| f.puts content }
This way, it will automatically call close when the block ends.
require 'fileutils.rb'
k=FileUtils.mkdir_p "d:/pptomasdsdr1xks_6b27"
filename = "#{k}""/kddabab"
extension = ".txt"
co=1
$stdout=File.open("#{filename}#{co}#{extension}" ,'w')
puts "sachin"
$stdout.close
puts "amit"
im getting error like
stdout.rb:14:in write': closed stream (IOError)
from stdout.rb:14:inputs'
i don't want amit to be printd in my file so that i close the file but i got this error
help me plzzz
Don't use $stdout to write to a file.
Don't change $stdout, and certainly not without storing away the old value somewhere so you can restore it after you're done with it.
Instead, call puts on the file object:
File.open("#{filename}#{co}#{extension}" ,'w') do |file|
file.puts "sachin" # This goes to the file
end
puts "amit" # This goes to standard output