How to Write to File in Ruby

How to write to file in Ruby?

The Ruby File class will give you the ins and outs of ::new and ::open but its parent, the IO class, gets into the depth of #read and #write.

How do I write to a file in Ruby?

The correct way:

file = File.join(File.dirname(__FILE__), 'test.txt')
File.open(file, 'w') { |f| f.puts 'hello' }

__FILE__ is the path to the file containing the above code, and since, your test.txt resides in the same directory as write_to_file.rb, this should work, regardless of which directory you are in, on your machine.

Also, note that, I have used puts method instead of write, since I prefer newlines. :)


Whats wrong with your Code (probably):

When you use test.txt, then the path is relative to the directory from where you are running your write_to_file.rb script. For example, if you run write_to_file.rb from your home directory, then test.txt will imply ~/test.txt.

Write to a file in Ruby with every iteration of a loop

Let's use IO::write to create two input files.

FNameIn1 = 'in1'
File.write(FNameIn1, "cow\npig\ngoat\nhen\n")
#=> 17

We can use IO::read to confirm what was written.

puts File.read(FNameIn1)
cow
pig
goat
hen

FNameIn2 = 'in2'
File.write(FNameIn2, "12\n34\n56\n78\n")
#=> 12
puts File.read(FNameIn2)
12
34
56
78

Next, use File::open to open the two input files for reading, obtaining a file handle for each.

f1 = File.open(FNameIn1)
#=> #<File:in1>
f2 = File.open(FNameIn2)
#=> #<File:in2>

Now open a file for writing.

FNameOut = 'out'
f = File.open(FNameOut, "w")
#=> #<File:out>

Assuming the two input files have the same number of lines, in a while loop read the next line from each, combine the two lines in some ways and the write the resulting line to the output file.

until f1.eof
line11 = f1.gets.chomp
line12 = f1.gets.chomp
line21 = f2.gets.chomp
line22 = f2.gets.chomp
f.puts "%s %s, %s %s" % [line11, line21, line12, line22]
end

See IO#eof, IO#gets and IO#puts.

Lastly, use IO#close to close the files.

f1.close
f2.close
f.close

Let's see that FileOut looks like.

puts File.read(FNameOut)
cow 12, pig 34
goat 56, hen 78

We can have Ruby close the files by using a block for each File::open:

File.open(FNameIn1) do |f1|
File.open(FNameIn2) do |f2|
File.open(FNameOut, "w") do |f|
until f1.eof
line11 = f1.gets.chomp
line12 = f1.gets.chomp
line21 = f2.gets.chomp
line22 = f2.gets.chomp
f.puts "%s %s, %s %s" % [line11, line21, line12, line22]
end
end
end
end
puts File.read FNameOut
cow 12, pig 34
goat 56, hen 78

This is in fact how it's normally done in Ruby, in part to avoid the possibility of forgetting to close files.

Here's another way, using IO::foreach, which, without a block, returns an enumerator, allowing the use of Enumerable#each_slice, as referenced in the question.

e1 = File.foreach(FNameIn1).each_slice(2)
#=> #<Enumerator: #<Enumerator: File:foreach("in1")>:each_slice(2)>
e2 = File.foreach(FNameIn2).each_slice(2)
#=> #<Enumerator: #<Enumerator: File:foreach("in2")>:each_slice(2)>

File.open(FNameOut, "w") do |f|
loop do
line11, line12 = e1.next.map(&:chomp)
line21, line22 = e2.next.map(&:chomp)
f.puts "%s %s, %s %s" % [line11, line21, line12, line22]
end
end
puts File.read(FNameOut)
cow 12, pig 34
goat 56, hen 78

We may observe the values generated by the enumerator

e1 = File.foreach(FNameIn1).each_slice(2)

by repeatedly executing Enumerator#next:

e1.next
#=> ["cow\n", "pig\n"]
e1.next
#=> ["goat\n", "hen\n"]
e1.next
#=> StopIteration (iteration reached an end)

The StopIteration exception, when raised, is handled by Kernel#loop by breaking out of the loop (which is one reason why loop is so useful).

Confusion about creating and writing to File in Ruby on rails

If you don't end along the filename as an option for send_data, it defaults to the method name.

Secondly, the download wants to read the data from a buffer. My guess is your syntax is just sending a file handle.

Try this...

send_data(file.read, filename: filename)

Or skip the intermediate file and try...

send_data(version_to_download.liquid_code.to_s, filename: filename)

ruby How to read a file and write to another file while skipping lines

File.open("output.txt", "w") do |file_to_write|
File.open("input.txt").each do |line|
if $. % 4 == 2
file_to_write.write(line.chomp)
end
if $. % 4 == 3
file_to_write.write(line)
end
end
end

Ruby has a special symbol which will give you the line number $. you can substitute that with File.open(filename).each_with_index do |line, index| and use index instead of $..
If you use an index you will need to add 1 to it, because it will start off at 0.

This code goes through your input file line-by-line. The lines starting from the second and third line and then each following line of interest is offset by 4.
Once we find the first half write that line to our opened file without a new line, once we find the second half (second if statement) write that line with a line terminator to the file.

How to write a file in specific path in ruby

Your code has multiple errors. Have you ever tried to execute the script?

Your script ends with:

test.rb:7: unknown regexp options - fldr
test.rb:7: syntax error, unexpected end-of-input
F = open.(Dir.pwd, /data/folder /#{@file_name },w+)

First: You need to define the strings with ' or ":

file_name = gets 
F = open.(Dir.pwd, "/data/folder/#{@file_name}","w+")

Some other errors:

  • You use file_name and later @file_name.
  • The open method belongs to File and needs two parameters.
  • The file is defined as a constant F. I would use a variable.
  • The path must be concatenated. I'd use File.join for it.
  • You don't close the file.

After all these changes you get:

file_name = gets
f = File.open(File.join(Dir.pwd, "/data/folder/#{file_name}"),"w+")
##
f.close

and the error:

  test.rb:29:in `initialize': No such file or directory @ rb_sysopen - C:/Temp/data/folder/sdssd (Errno::ENOENT)

The folder must exist, so you must create it first.

Now the script looks like:

require 'fileutils'
dirname = "data/folder"
file_name = gets.strip
FileUtils.mkdir_p(dirname) unless Dir.exists?(dirname)
f = File.open(File.join(Dir.pwd, dirname, file_name),"w+")
##fill the content
f.close

How to write variables in a file?

You can call write:

userId = 76
userkey = "UtRzoP"
configFile = File.new("file.txt", "w")
configFile.write("id=#{userId}\nkey=#{userkey}")
configFile.close

As others in the comments point out, you can do the same with blocks:

File.open("file.txt", "w") { |f| f.write("id=#{userId}\nkey=#{userkey}") }

PS: puts puts a new line at the end of the string when written to a file. Personally, I favor write because it doesn't put that last new line in the end.

How to create a file in Ruby

Use:

File.open("out.txt", [your-option-string]) {|f| f.write("write your stuff here") }

where your options are:

  • r - Read only. The file must exist.
  • w - Create an empty file for writing.
  • a - Append to a file.The file is created if it does not exist.
  • r+ - Open a file for update both reading and writing. The file must exist.
  • w+ - Create an empty file for both reading and writing.
  • a+ - Open a file for reading and appending. The file is created if it does not exist.

In your case, 'w' is preferable.

OR you could have:

out_file = File.new("out.txt", "w")
#...
out_file.puts("write your stuff here")
#...
out_file.close

How to write a file with ruby?

I think you would do better using Ruby's TempFile class and perhaps even Ruby's temp dir as suggested in this article: Quick tips for doing IO with Ruby.

I think you will find the article helpful. I believe it will make your approach easier - especially regarding deleting the file once you're done with it.

How do I save the text of puts in Ruby to a txt file?

There are ways to save the output of a script to a file without having to modify every puts in the script.

The easiest is to route the output at the command-line using redirection. Running a script with > some_file at the of the command will route all STDOUT to the file. Similarly, using > some_file 2>&1 will route both STDOUT and STDERR to the same file. This won't capture anything typed in at a gets as the code waits for input though, because that won't count as program output.

If you don't mind changing your code a little, you can temporarily change the interpreter's idea of what STDOUT is by reassigning it to a file:

old_stdout = $stdout
File.open('output.txt', 'w') do |fo|
$stdout = fo

# ----
# your code goes here
puts "hello world"
# ----

end
$stdout = old_stdout

Run that, then look at the file "output.txt" and you'll see "hello world", even though we didn't print to the file-handle fo directly, like we would normally do using fo.puts.

There are a variety of ways of doing the same thing but they amount to pointing STDOUT or STDERR somewhere else, writing to them, then resetting them.

Typically, if we intend from the start to output to a file, then we should use a File.open block:

File.open('output.txt', 'w') do |fo|
fo.puts "hello world"
end

The benefit of that is the file will be closed automatically when the block exits.



Related Topics



Leave a reply



Submit