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.
Related
I've got this program that starts off with the program grabbing a file's contents.
local oldprint = print
local print = io.write
-- this was done mainly because the newline from print() wasn't needed
io.input("script.txt")
local script = io.read("*all")
io.close()
Then there is a function containing another io.read(), which should allow for the user's input.
local functions = {
[","] = function()
local input
repeat
print("\nAwaiting input... (must be a number)\n")
input = io.read("*n")
until input ~= nil
array[pointer] = input
print(stringy)
end
}
functions[","]()
I expect it for it to print once, and then grab the input, but it ends up constantly printing.
I've tried using io.flush(), but it didn't work, and I'm not exactly sure what else to try...
By calling io.input("script.txt") you set that file as the default input file. Any following calls to io.read() will hence read from that file.
Either use file:read instead of io.read or reset the input to the standard input stream by calling io.input(io.stdin).
I suggest you refer to the Lua reference manual.
https://www.lua.org/manual/5.4/manual.html#6.8
To use io.read(), you have to close the file you opened, because if you have a file open, lua will assume you are reading from the file that you opened.
Try grabbing the input before you open the file
I am learning the Lua IO library. I'm having trouble with io.write(). In Programming Design in Lua, there is a piece of code that iterates through the file line by line and precedes each line with a serial number.
This is the file I`m working on:
test file: "iotest.txt"
This is my code
io.input("iotest.txt")
-- io.output("iotest.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
This is the result of the terminal display, but this result cannot be written to the file, whether I add IO. Output (" iotest.txt ") or not.
the results in terminal
This is the result of file, we can see there is no change
The result after code running
Just add io.flush() after your write operations to save the data to the file.
io.input("iotest.txt")
io.output("iotestout.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
io.flush()
io.close()
Refer to Lua 5.4 Reference Manual : 6.8 - Input and Output Facilities
io.flush() will save any written data to the output file which you set with io.output
See koyaanisqatsi's answer for the optional use of file handles. This becomes especially useful if you're working on multiple files at a time and gives you more control on how to interact with the file.
That said you should also have different files for input and output. You'll agree that it doesn't make sense to read and write from and to the same file alternatingly.
For writing to a file you need a file handle.
This handle comes from: io.open()
See: https://www.lua.org/manual/5.4/manual.html#6.8
A file handle has methods that acts on self.
Thats the function after the : at file handle.
So io.write() puts out on stdout and file:write() in a file.
Example function that can dump a defined function to a file...
fdump=function(func,path)
assert(type(func)=="function")
assert(type(path)=="string")
-- Get the file handle (file)
local file,err = io.open(path, "wb")
assert(file, err)
local chunk = string.dump(func,true)
file:write(chunk)
file:flush()
file:close()
return 'DONE'
end
Here are the methods, taken from io.stdin
close = function: 0x566032b0
seek = function: 0x566045f0
flush = function: 0x56603d10
setvbuf = function: 0x56604240
write = function: 0x56603e70
lines = function: 0x566040c0
read = function: 0x56603c90
This makes it able to use it directly like...
( Lua console: lua -i )
> do io.stdout:write('Input: ') local result=io.stdin:read() return result end
Input: d
d
You are trying to open the same file for reading and writing at the same time. You cannot do that.
There are two possible solutions:
Read from file X, iterate through it and write the result to another file Y.
Read the complete file X into memory, close file X, then delete file X, open the same filename for writing and write to it while iterating through the original file (in memory).
Otherwise, your approach is correct although file operations in Lua are more often done using io.open() and file handles instead of io.write() and io.read().
I have a simple function to read lines from .txt file:
function loadData(file_name, root_path)
-- here, file_name is './list.txt', path is '../data/my/'
for line in io.lines(file_name) do
local data = {}
base_path = root_path .. line
-- so, base_path is something like ../data/my/001
data.file = base_path .. '_color.png'
print(data)
end
end
I expect the data should be {file: "../data/my/001_color.png"}, but I got {_color.png" ../data/my/001}
Can anyone help me? Thanks!
Check your ./list.txt file content for EOL (end of line) as it may be produced on windows (EOL=CR LF) an interpreted on linux (EOL=LF). io.lines takes CR character into line string on linux!
Your programm makes everything correct, but your data is not.
Let assume your first line in ./list.txt is ../data/my/001\r\n
line variable is ../data/my/001\r (print(#line) gives 15 instead of 14 ).
Carriage return (CR) in print moves cursor to start line position witout changing line.
Your print output in this case is something simmilar to {file: "../data/my/001\r_color.png"} (as it depends on print implementation) and you get output:
{file: "../data/my/001
_color.png"} <-- on the same line
Let's combine it:
_color.png"}ata/my/001
To correct this:
provide file without CR (works correctly on all systems)
add in loop on first row: line = line:gsub('[\r\n]','') to remove CR LF
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
I am having some trouble writing a file to a specific path taking the file name from excel. Here is the code which I am using
out_file = File.new (#temp_path/ "#{obj_info[3].to_s}","w")
"#{obj_info[3].to_s}" = sample.txt
The value sample.txt comes from Excel during run time
#temp_path = "C:/Users/Somefolder/"
The error displayed is:
NoMethodError: undefined method `[]' for nil:NilClass
However, if the code is:
out_file = File.new ("#{obj_info[3].to_s}","w")
it successfully creates a file called sample.txt in the default directory. However, I want it to be stored in a specific directory and the file name needs to be passed from Excel.
Any help is much appreciated.
I believe your problem is because there a space between / and "
#temp_path/ "#{obj_info[3].to_s}
and I guess you want to build a path.
My advice is that you use File.join
f_path = File.join(#temp_path,obj_info[3].to_s)
out_file = File.new (f_path,"w")
Let me know if that solved the problem
You have 2 problems:
obj_info is nil so you make an error reading the value from excel, the error you get indicates it is on an array, in the code you published the only thing that's an array is what you read from excel.
Print the contents with p obj_info right before your code to check.
#temp_path and {obj_info[3].to_s} need to be concatenated to make a path.
You can do that with File.join like Mauricio suggests or like this
out_file = File.new ("#{#temp_path}/#{obj_info[3]}","w")
You can drop the to_s in this case.
It would be better if you publish the whole of your script that is meaningful.