Ruby: overwrite line in file - ruby

I am trying to log some state to a file using standard file i/o in ruby. The file will just have one line with a number in it. I want to read in the line and then on each iteration of a loop I want to update this number.
I know I can read in the file with
file = File.open('out.log', 'a+')
num = file.readline
The problem is, I don't know how to then overwrite the first line in a loop without just re-opening the file every iteration i.e.
file = File.open('out.log', 'w')
which will create an empty file

No need to open it each time:
file = File.open('out.log', File::RDWR)
10.times do |i|
file.seek(0) # rewind to the beginning of the file (line in your case)
file.write("iteration #{i}") # write what you want
# the following is just in order to show what was written
file.seek(0)
puts file.readline
end
file.close

You can use IO::open with block to close the file, when block exits automatically.
File.open("#{__dir__}/test.txt", File::RDWR) do |file|
10.times do |i|
file.rewind
file.puts("iteration #{i}")
end
end
puts File.read("#{__dir__}/test.txt")
# >> iteration 9

Related

ruby write all lines of puts in file?

I have my file
ppp.txt
mmm;2;nsfnjd;pet;
sadjjasjnsd;6;gdhjsd;pet;
gsduhdssdj;3;gsdhjhjsd;dog;
I need to write
nsfnjd
gsdhjhjsd
I use this code but only print the last line "gsdhjhjsd"
I dont know what is doing wrong
File.open("ppp.txt", "r") do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
if parts[1].to_i < 4
puts parts[2]
File.open("testxx.txt", "w+") do |f|
f. puts parts[2]
end
end
end
end
Please help me
Open the file using append mode, 'a+' instead of write mode 'w+', which overwrites the file, as the open command is called inside a loop.
Or open the write file prior to looping the lines of the read file.
open the file descriptor outside the loop
fo = File.open("testxx.txt","w+")
File.open("ppp.txt", "r") do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
fo.puts parts[2] if parts[1].to_i < 4
end
end
fo.close()
NOTE: Need to explicitly close fo, but file open with block; ruby close the file automatically (fi case).

Printing lines from a file in ruby

When I start printing lines from a file, I get this error
#<File:0x007ff65ee297b0>
Here is the code
require 'rubygems'
File.open("sample.txt", 'r') do |f|
puts f
end
You are printing the file object. To get the contents line by line, you can use File.foreach
File.foreach('sample.txt', 'r') do |line|
puts line # called for every line
end
To process the whole file at once, you can use the read method on the file object:
File.open('sample.txt', 'r') do |file|
puts file.read # called only once
end
This is not an error. It prints correctly one line which is your File object.
Here your create a file object and you did not ask it to fetch lines or anything else for that matter.
Several good answers already. But here is another way to do it with minimal change to your code:
File.open("sample.txt", 'r').each_line do |f|
puts f
end
Another way :
IO.foreach("sample.txt") {|line| line }
Or
File.foreach('sample.txt') {|line| line }
File::open returns file handle (which apparently is being printed out as #<File:0x007ff65ee297b0>.) If you need the file content line by line you might want to use IO::readlines:
IO.readlines("sample.txt").each do |line|
puts line
end

read file and send data to yml file

i read multipe file and i try to get data in yaml file, but i dont know why i get nothing in my yaml file .
Do you have an idea where i can make a mistake ?
a = array.size
i = 0
array.each do |f|
while i < a
puts array[i]
output = File.new('/home/zyriuse/documents/Ruby-On-Rails/script/Api_BK/licence.yml', 'w')
File.readlines(f).each do |line|
output.puts line
output.puts line.to_yaml
#output.puts YAML::dump(line)
end
i += 1
end
end
There's two problems...
You are initializing i to zero too early... when you process the
first file 'f' you process JUST that first file as many times as you
have files in the array, but for all following files i is now always >= a so you're not doing anything with them.
You are doing File.new in every iteration of 'f' so you are wiping out your last iteration.
This might work better...
output = File.new('licence.yml', 'w')
array.each do |f|
puts f
File.readlines(f).each do |line|
output.puts line
output.puts line.to_yaml
end
end

Ruby: Append text to the 2nd line of a file

The Ruby script i am writing is going to be run every morning and will pull information about backup files and write them to a csv file. This file has column names on the first line.
I have gotten it to work by appending to the end of the file:
open("#{curDir}/Backup_Times.csv", 'a') do |f|
...
end
I would like to see the newest data first without having to sort in Excel.
In Ruby, is there a way to write this data starting at the 2nd line of the file?
You write a new file, applying your change at the desired line, then rename result back to the original file name. The following method will copy the file and yield the output file object to a block at the correct line, so that block can output your new lines.
def insert_lines_following_line file, line_no
tmp_fn = "#{file}.tmp"
File.open( tmp_fn, 'w' ) do |outf|
line_ct = 0
IO.foreach(file) do |line|
outf.print line
yield(outf) if line_no == (line_ct += 1)
end
end
File.rename tmp_fn, file
end
insert_lines_following_line( "#{curDir}/Backup_Times.csv", 1 ) do |outf|
# output new csv lines in this block
outf.puts ['foo','bar','baz',1,2,3].join(",") # or however you build your csv line
end

Read Certain Lines from File

Hi just getting into Ruby, and I am trying to learn some basic file reading commands, and I haven't found any solid sources yet.
I am trying to go through certain lines from that file, til the end of the file.
So in the file where it says FILE_SOURCES I want to read all the sources til end of file, and place them in a file.
I found printing the whole file, and replacing words in the file, but I just want to read certain parts in the file.
Usually you follow a pattern like this if you're trying to extract a section from a file that's delimited somehow:
open(filename) do |f|
state = nil
while (line = f.gets)
case (state)
when nil
# Look for the line beginning with "FILE_SOURCES"
if (line.match(/^FILE_SOURCES/))
state = :sources
end
when :sources
# Stop printing if you hit something starting with "END"
if (line.match(/^END/))
state = nil
else
print line
end
end
end
end
You can change from one state to another depending on what part of the file you're in.
I would do it like this (assuming you can read the entire file into memory):
source_lines = IO.readlines('source_file.txt')
start_line = source_lines.index{ |line| line =~ /SOURCE_LINE/ } + 1
File.open( 'other_file.txt', 'w' ) do |f|
f << source_lines[ start_line..-1 ].join( "\n" )
end
Relevant methods:
IO.readlines to read the lines into an array
Array#index to find the index of the first line matching a regular expression
File.open to create a new file on disk (and automatically close it when done)
Array#[] to get the subset of lines from the index to the end
If you can't read the entire file into memory, then I'd do a simpler variation on #tadman's state-based one:
started = false
File.open( 'other_file.txt', 'w' ) do |output|
IO.foreach( 'source_file.txt' ) do |line|
if started then
output << line
elsif line =~ /FILE_SOURCES/
started = true
end
end
end
Welcome to Ruby!
File.open("file_to_read.txt", "r") {|f|
line = f.gets
until line.include?("FILE_SOURCES")
line = f.gets
end
File.open("file_to_write.txt", "w") {|new_file|
f.each_line {|line|
new_file.puts(line)
}
new_file.close
}
f.close
}
IO functions have no idea what "lines" in a file are. There's no straightforward way to skip to a certain line in a file, you'll have to read it all and ignore the lines you don't need.

Resources