Reading Files in Ruby - ruby

So, I'm relatively new to programming, and I have started working with ruby. I am going through "Learn how to code the hard way: Ruby" and I am on exercise 15; the beginning of file reading. I have copied the code they provided word for word, literally copy and pasted it to make sure, but I am getting the same error. I've googled the error, but to no avail. I have the .rb file in the same directory as the .txt file I'm trying to read. Here is my code.
filename = ARGV.first
prompt = "> "
txt = File.open(filename)
puts "Here's your file: #{filename}"
puts txt.read()
puts "I'll also ask you to type it again:"
print prompt
file_again = STDIN.gets.chomp()
txt_again = File.open(file_again)
puts txt_again.read()
The error I keep getting it this:
ex15.rb:19:in 'initialize': No such file of directory - ex15.txt <Errno::ENOENT>
from ex15.rb:4:in 'open'
from ex15.rb:4:in '<main>'
command to run it:
ruby ex15.rb ex15.txt
Any help is appreciated. Thanks

When you don't specify the mode argument for File.open(), the default is 'r', which stands for read. And to read a file, it has to exist already. The error message is telling you that there is no file named 'ex15.txt' in the current directory for ruby to read.
To get rid of the error, create a file called ex15.txt in the current directory, and type 'hello world' in the file.

Related

Ruby read file_name with gets

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"

Opening a Text File in Ruby

I am trying to create a program that will count the word frequency within a text file that I have created. I have a text file titled moms_letter.txt and this is my code:
word_count = {}
File.open("moms_letter.txt", "r") do |f|
f.each_line do |line|
words = line.split(' ').each do |word|
word_count[word] += 1 if word_count.has_key? word
word_count[word] = 1 if not word_count.has_key? word
end
end
end
puts word_count
The problem I am getting is when I go to run the file, I get the error:
there is no such file or directory - moms_letter.txt (Errno: : ENOENT)
Not quite sure why this is occurring when I have the text file created.
Any help is appreciated.
I am also newbie in Ruby, so thanks for the patience.
You must be executing your program from outside the directory where your moms_letter.txt file resides. You need to use an absolute path to open your file. Or, execute your program always from the directory where the .txt is. So, instead of using "moms_letter.txt" go with "complete/path/to/file/moms_letter.txt".
I'm fairly new to Ruby too, but have worked with text files a bit recently. It may seem like an obvious question, but is the text file you're trying to open in the same directory as your .rb file? Otherwise you'll need to include the relative path to it.
For troubleshooting sake, try File.new("temp.txt", "w") and then File.open("temp.txt", "r") to see if that works. Then you'll know if it's an issue with your code or with the txt file you're trying to access.
Also using File.exists?("moms_letter.txt") will help you determine whether you can access that file from within your .rb script.
Hope that helps!

Ruby: Reading from a file written to by the system process

I'm trying to open a tmpfile in the system $EDITOR, write to it, and then read in the output. I can get it to work, but I am wondering why calling file.read returns an empty string (when the file does have content)
Basically I'd like to know the correct way of reading the file once it has been written to.
require 'tempfile'
file = Tempfile.new("note")
system("$EDITOR #{file.path}")
file.rewind
puts file.read # this puts out an empty string "" .. why?
puts IO.read(file.path) # this puts out the contents of the file
Yes, I will be running this in an ensure block to nuke the file once used ;)
I was running this on ruby 2.2.2 and using vim.
Make sure you are calling open on the file object before attempting to read it in:
require 'tempfile'
file = Tempfile.new("note")
system("$EDITOR #{file.path}")
file.open
puts file.read
file.close
file.unlink
This will also let you avoid calling rewind on the file, since your process hasn't written any bytes to it at the time you open it.
I believe IO.read will always open the file for you, which is why it worked in that case. Whereas calling .read on an IO-like object does not always open the file for you.

ERRNO::EACCES in String substitution

I'm trying to write a program which substitutes a string.
require File.join(APP_ROOT, 'lib', 'main.rb')
files_names = Dir.entries("../DeSpacer")
files_names.each do |file_name|
File.open("#{file_name}", "w") do |text|
text.each {|line| line.gsub!(/\.\s{2,}/, "\.\s")}
end
end
I keep getting a
Permission denied -. (ERRNO::EACCES)
Can you explain what I am doing wrong?
The initial problem is that you're only opening the file for writing ('w'), and not reading, and thus receiving the exception.
As the comments above mention, there are other issues with the code as well.
This answer gives a more typical way to do what you're trying to do.
As mentioned in another answer to the same question, Ruby also has a command line shortcut inherited from Perl which makes things like this trivial:
ruby -pi.bak -e "gsub(/oldtext/, 'newtext')" *.txt
This will edit a file or files in place, backing up the previous version with a suffix of '.bak'.
From Programming Ruby:
-i [extension}
' Edits ARGV files in place. For each file named in ARGV, anything you write to
standard output will be saved back as the contents of that file. A backup copy of
the file will be made if extension is supplied.
% ruby -pi.bak -e "gsub(/Perl/, 'Ruby')" *.txt

How to read an open file in Ruby

I want to be able to read a currently open file. The test.rb is sending its output to test.log which I want to be able to read and ultimately send via email.
I am running this using cron:
*/5 * * * /tmp/test.rb > /tmp/log/test.log 2>&1
I have something like this in test.rb:
#!/usr/bin/ruby
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
When I run this code, it only gives me this output:
Start
End
I would expect the output to be something like this:
Start
Start (from the reading of the test.log since it should have the word start already)
End
Ok, you're trying to do several things at once, and I suspect you didn't systematically test before moving from one step to the next.
First we're going to clean up your code:
def read_file(file_name)
file = File.open(file_name, "r")
data = file.read
file.close
return data
end
puts "Start"
puts read_file("/tmp/log/test.log")
puts "End"
can be replaced with:
puts "Start"
puts File.read("./test.log")
puts "End"
It's plain and simple; There's no need for a method or anything complicated... yet.
Note that for ease of testing I'm working with a file in the current directory. To put some content in it I'll simply do:
echo "foo" > ./test.log
Running the test code gives me...
Greg:Desktop greg$ ruby test.rb
Start
foo
End
so I know the code is reading and printing correctly.
Now we can test what would go into the crontab, before we deal with its madness:
Greg:Desktop greg$ ruby test.rb > ./test.log
Greg:Desktop greg$
Hmm. No output. Something is broken with that. We knew there was content in the file previously, so what happened?
Greg:Desktop greg$ cat ./test.log
Start
End
Cat'ing the file shows it has the "Start" and "End" output of the code, but the part that should have been read and output is now missing.
What happening is that the shell truncated "test.log" just before it passed control to Ruby, which then opened and executed the code, which opened the now empty file to print it. In other words, you're asking the shell to truncate (empty) it just before you read it.
The fix is to read from a different file than you're going to write to, if you're trying to do something with the contents of it. If you're not trying to do something with its contents then there's no point in reading it with Ruby just to write it to a different file: We have cp and/or mv to do those things for us witout Ruby being involved. So, this makes more sense if we're going to do something with the contents:
ruby test.rb > ./test.log.out
I'll reset the file contents using echo "foo" > ./test.log, and cat'ing it showed 'foo', so I'm ready to try the redirection test again:
Greg:Desktop greg$ ruby test.rb > ./test.log.out
Greg:Desktop greg$ cat test.log.out
Start
foo
End
That time it worked. Trying it again has the same result, so I won't show the results here.
If you're going to email the file you could add that code at this point. Replacing the puts in the puts File.read('./test.log') line with an assignment to a variable will store the file's content:
contents = File.read('./test.log')
Then you can use contents as the body of a email. (And, rather than use Ruby for all of this I'd probably do it using mail or mailx or pipe it directly to sendmail, using the command-line and shell, but that's your call.)
At this point things are in a good position to add the command to crontab, using the same command as used on the command-line. Because it's running in cron, and errors can happen that we'd want to know about, we'd add the 2>&1 redirect to capture STDERR also, just as you did before. Just remember that you can NOT write to the same file you're going to read from or you'll have an empty file to read.
That's enough to get your app working.
class FileLineRead
File.open("file_line_read.txt") do |file|
file.each do |line|
phone_number = line.gsub(/\n/,'')
user = User.find_by_phone_number(line)
user.destroy unless user.nil?
end
end
end
open file
read line
DB Select
DB Update
In the cron job you have already opened and cleared test.log (via redirection) before you have read it in the Ruby script.
Why not do both the read and write in Ruby?
It may be a permissions issue or the file may not exist.
f = File.open("test","r")
puts f.read()
f.close()
The above will read the file test. If the file exists in the current directory
The problem is, as I can see, already solved by Slomojo. I'll only add:
to read and print a text file in Ruby, just:
puts File.read("/tmp/log/test.log")

Resources