Read next line during file IO in Ruby - ruby-on-rails

I am trying to import a file using ruby and parse it. Is there a way to read the next line once inside the file import? Basically I want to see if a specific line is within x lines of another important line. Like does "x phrase" Come within 10 lines of "y phrase". I don't see a way to do this -- I know its simple with Java.
Thanks!

You can also try:
web_contents = "c:\\path\\to\\your\\file.txt"
File.open(web_contents).each_with_index do |line, i|
line.chomp!
puts "line #{line}, i #{i}" # Do whatever you want to here
end
The .each_with_index method gives you an index, i, which you can use to keep track of where on what line in your file you are. Simple maths can then yield the offset as required.

To read lines of a file
lines_array = IO.readlines('testfile')
lines_array.each { |l| #Do your stuff with your line }
VoilĂ 
Ruby Docs on IO

Related

Add a specific line from a document.txt to a comment field with specific id and then move to next line?

How can I add a specific line from my document.txt to YouTube comment field with specific id and then move to next line on my document.txt. The id of YouTube comment field is 'contenteditable-root'. I have created this code but the text that is been added on the YouTube comment field show in brackets for example ["Hello"]
Or in second example it shows nothing
Example 1:
file = 'comments.txt'
File.readlines(file).each do |i|
files = [i]
files.each { |val|
browser.execute_script("document.getElementById('contenteditable-root').innerHTML = '#{files}';")
}
end
Example 2:
line_number = 1
loop do
comments = IO.readlines('comments.txt')[line_number-1]
browser.execute_script("document.getElementById('contenteditable-root').innerHTML = '#{comments}';")
line_number += 1
end
comment.txt file:
Hellooo !!
hi
Goodbye
Goodnight
Assuming a whole bunch of other things here are correct, you're doing a very weird iteration, you should just use:
file = 'comments.txt'
File.readlines(file).each do |i|
browser.execute_script("document.getElementById('contenteditable-root').innerHTML = '#{i}';")
end
Seems to me like you need to learn how to debug.
Step 1: Check in irb (about irb) if your code is printing the correct text:
File.readlines('comments.txt').each do |line|
p line
end
Expected output:
=> "Line 1"
=> "Line 2"
=> "Line 3"
If not, then look up how to read a file per line.
Step 2: Does your piece of Javascript actually work?
Go to the page you're trying to test, Open the debugger (F12) and run your Javascript directly from the console:
document.getElementById('contenteditable-root').innerHTML = 'hi';
If it doesn't work, then try learning more abut Javascript on how it works interacting with elements.
Step 3: Does my piece of code actually work from Watir?
Open up irb again and try it out
require 'watir'
b = Watir::Browser.new
b.goto 'https://youryoutubepage.com/path'
b.execute_script("document.getElementById('contenteditable-root').innerHTML = 'hi';")
If it fails, google the error, look for Watir and execute_script.
Then finally run the whole combination of your code in irb:
require 'watir'
b = Watir::Browser.new
b.goto 'https://youryoutubepage.com/path'
File.readlines('comments.txt').each do |line|
b.execute_script("document.getElementById('contenteditable-root').innerHTML = 'hi';")
sleep 5 # Give yourself some time to visually confirm the changes.
end
A quick Google about your SyntaxError: Invalid or unexpected token (Selenium::WebDriver::Error::UnknownError) I see it might be a problem with the quotations that execute_script doesn't like.
Maybe try reversing the quotes:
b.execute_script('document.getElementById("contenteditable-root").innerHTML = "hi";')
In the future, please try to pinpoint your problem and don't use StackOverflow as a place to debug your code. Get your code to work step by step and focus your question on a specific function that's not working as expected.

What does file.new("temp.out", "w") line represent?

I'm learning the Ruby language and I'm having a lot of fun.
I am currently working on the Temperature converter with file output exercise.
The solution is provided below
print "Hello. Please enter a Celsius value: "
celsius = gets.to_i
fahrenheit = (celsius * 9 / 5) + 32
puts "saving result to output file 'temp.out'"
fh = File.new("temp.out", "w")
fh.puts fahrenheit
fh.close
The highlighted part confuses me.
We are calling File.new to create a file named "temp.out" and "w" write whatever inputs until we fh.close. Am I correct?
Thank you!
By default, puts() will send its output to what's called stdout, which is connected to your screen. File.new() creates a new file which is assigned to the variable fh. Because you created the file in write mode, you can use fh to write stuff to the file. fh.puts() sends output to the file assigned to the variable fh. In other words, a bare puts() statement sends output to your screen, but when you precede puts() with a file, the output goes to the file.
You can also write those statements like this:
File.open("temp.out", "w") do |f|
f.puts fahrenheit
end
The neat thing about writing it like that is: when the end statement executes, Ruby will automatically close the file for you.

CSV.open(..) block does not execute, and ends immediately

I am opening a CSV file for writing with the following code, as indicated in CSV documentation here (http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html):
CSV.open( csv_file_out, 'wb' ) { |csv_line_out|
#stuff happens here
}
the block does not execute, i.e. after the CSV.open command debugger goes directly to the end of block.
thinking "just in case", I try the same with IO modes w+b wt w+t ab a+b. I also tried creating the file before the in case there was a problem with opening it. nothing changes.
when I stop the debugger at the CSV.open line, I am able to execute a block manually and create a csv file myself. I can also create the file frmo the exact same command from console. But it won't work when executed in the server.
Any ideas on what's going on are very welcome. Thanks in advance!
You don't need the {} brackets before your |csv_line_out|
Your trying to iterate sth. (the files content) that does not exist so its logical that it ends imediatly! Try it this way:
CSV.open(csv_file_out, "wb") do |csv|
csv << [column1, column2,...]
end

How to insert a string into a textfile

I have a configuration file to which I want to add a string, that looks e.g. like that:
line1
line2
line3
line4
The new string should not be appended but written somewhere into the middle of the file. Therefore I am looking for a specific position (or string) in the file and when it has been found, I insert my new string:
file = File.open(path,"r+")
while (!file.eof?)
line = file.readline
if (line.downcase.starts_with?("line1"))
file.write("Some nice little sentence")
end
end
The problem is that Ruby overwrites the line in that position with the new text, so the result is the following:
line1
Some nice little sentence
line3
line4
What I want is a "real" insertion:
line1
Some nice little sentence
line2
line3
line4
How can this be achieved?
If it's a small file I think the easiest way would be to:
Read the complete file.
Insert the line.
Write the new file.
That is the way Rails does it behind the scenes.
Or you can copy it line by line and then overwrite the original with mv like this:
require 'fileutils'
tempfile=File.open("file.tmp", 'w')
f=File.new("file.txt")
f.each do |line|
tempfile<<line
if line.downcase=~/^line2/
tempfile << "Some nice little sentence\n"
end
end
f.close
tempfile.close
FileUtils.mv("file.tmp", "file.txt")
def replace(filepath, regexp, *args, &block)
content = File.read(filepath).gsub(regexp, *args, &block)
File.open(filepath, 'wb') { |file| file.write(content) }
end
replace(my_file, /^line2/mi) { |match| "Some nice little sentence"}
line1
Some nice little sentence
line2
line3
line4
and if you want to append to the existing...
replace(my_file, /^line2/mi) do |match|
"#{match} Some nice little sentence"
end
line1
line2 Some nice little sentence
line2
line3
line4
A couple other options:
file = File.read(path).sub(/line2\n/, 'Some nice little sentence\n\1')
File.write(path, file)
file = File.readlines(path)
index = file.index("line2")
file.insert(index, "Some nice little sentence")
File.write(path, file)
The easiest way is to read the whole file in memory, then write the first part back to the file, write your inserted line to the file, and write the remaining part back to the file. This should be relatively simple to do when you read the file as an array of lines, but you might run into problems if your file is very large since you have to read the entire file into memory with this approach.
Alternatively you could find the spot that you want to insert the line, read the lines after that point into memory, seek back to that point in the file, write your new line to the file, and finally write the remaining lines to the file. Again you'll run into problems if the remainder of the file is very large since you have to read it all into memory.
A third approach is to write the first part into a new file, write the inserted line into a new file, write the remainder of the original file into the new file, and finally replace the old file with the new file on the file system. This approach allows you to deal with one line at a time so you can handle files that do not fit into memory.
The reason why file writing works like this is because the file is like a fixed size array of bytes: when you write a byte to the file you will overwrite an existing byte (I'm ignoring the case where you append to a file here). So the only way to insert anything to a file is to first move the old content to a new location by reading it from the old location and writing it to the new location. After that you can 'insert' data into the now vacant area.
The tty-file gem has an inject_into_file method for this purpose.
Install the gem:
gem install tty-file
Then:
require 'tty-file'
TTY::File.inject_into_file("filename.rb", "Some nice little sentence", after: "line1\n")

Reading the first line of a file in Ruby

I want to read only the first line of a file using Ruby in the fastest, simplest, most idiomatic way possible. What's the best approach?
(Specifically: I want to read the git commit UUID out of the REVISION file in my latest Capistrano-deployed Rails directory, and then output that to my tag. This will let me see at an http-glance what version is deployed to my server. If there's an entirely different & better way to do this, please let me know.)
This will read exactly one line and ensure that the file is properly closed immediately after.
strVar = File.open('somefile.txt') {|f| f.readline}
# or, in Ruby 1.8.7 and above: #
strVar = File.open('somefile.txt', &:readline)
puts strVar
Here's a concise idiomatic way to do it that properly opens the file for reading and closes it afterwards.
File.open('path.txt', &:gets)
If you want an empty file to cause an exception use this instead.
File.open('path.txt', &:readline)
Also, here's a quick & dirty implementation of head that would work for your purposes and in many other instances where you want to read a few more lines.
# Reads a set number of lines from the top.
# Usage: File.head('path.txt')
class File
def self.head(path, n = 1)
open(path) do |f|
lines = []
n.times do
line = f.gets || break
lines << line
end
lines
end
end
end
You can try this:
File.foreach('path_to_file').first
How to read the first line in a ruby file:
commit_hash = File.open("filename.txt").first
Alternatively you could just do a git-log from inside your application:
commit_hash = `git log -1 --pretty=format:"%H"`
The %H tells the format to print the full commit hash. There are also modules which allow you to access your local git repo from inside a Rails app in a more ruby-ish manner although I have never used them.
first_line = open("filename").gets
I think the jkupferman suggestion of investigating the git --pretty options makes the most sense, however yet another approach would be the head command e.g.
ruby -e 'puts `head -n 1 filename`' #(backtick before `head` and after `filename`)
Improving on the answer posted by #Chuck, I think it might be worthwhile to point out that if the file you are reading is empty, an EOFError exception will be thrown. Catch and ignore the exception:
def readit(filename)
text = ""
begin
text = File.open(filename, &:readline)
rescue EOFError
end
text
end
first_line = File.readlines('file_path').first.chomp

Resources