I'm reading a file line by line in a simple program and when I print the the lines to the screen the last line can't be seen at the ouput window in Netbeans 6.5.1 IDE on Windows XP but when I run the program directly from the command line as "ruby main.rb" there is not a problem (i.e the last line can be seen).I'm using Ruby 1.8.6.Here is the entire code :
File.open("songs.txt","r") do |file|
file.each do |line|
print line
end
end
This will work better if you use puts which will append a newline terminator if there is not already one at the end of the line, forcing a buffer flush.
I've never run across this before myself, but my guess would be that your final line doesn't have a trailing line break, so the Netbeans console isn't flushing the line. Try adding $stdout.flush at the end of the program and see what happens.
By the way, you can simplify this code slightly by rewriting it using foreach:
File.foreach("songs.txt","r") do |file|
print line
end
Related
I try to run an external command in Ruby, and parse its output .
IO.popen(command, :err=>[:child, :out]) {|ls_io|
ls_io.each do |line|
print line
end
}
This way of doing it works wonders… except when I parse the progress-output of a c-program that shows it progress to stdout with \r.
As long as the c-program has not outputted a \n (that is as long as it has not finished some long-operation), Ruby waits and sees nothing. Then when a \n is outputted, Ruby sees it all
1%\r2%\r3%\r…100%
task finished
I tried all of the many ways to call external commands (eg Calling shell commands from Ruby) ; but none seem to capture the progress. I also tried every opeartor such as STDOUT.sync = true, and the c-program does call fflush(stdout)
I finally found a workaroud. I do :
IO.popen(commande, :err=>[:child, :out]) {|ls_io|
while true
byte=ls_io.read(1)
if byte.nil?
break
end
print byte
end
}
It's stupid… but it works.
Any more elegant way, and much more efficient way to do this ? Performance is terrible, as if the "refresh rate" was slow.
Set the input record separator to "\r" right before your block (provided you know it in advance):
$/ = "\r"
Reference of global preset variables: http://www.zenspider.com/Languages/Ruby/QuickRef.html#pre-defined-variables
I am learning Ruby and am messing with reading/writing files right now. When I create the file, 'filename', I can write to it with the .write() method. However, I cannot output the content to the terminal without reopening it after running .read() on it (see line 8: puts write_txt.read()). I have tried running line 8 multiple times, but all that does is output more blank lines. Without line 8, puts txt.read() simply outputs a blank line. The following code also works without the puts in line 8 (simply write_txt.read())
# Unpacks first argument to 'filename'
filename = ARGV.first
# Lets write try writing to a file
write_txt = File.new(filename, 'w+')
write_txt.write("OMG I wrote this file!\nHow cool is that?")
# This outputs a blank line THIS IS THE LINE IN QUESTION
puts write_txt.read()
txt = File.open(filename)
# This actually outputs the text that I wrote
puts txt.read()
Why is this necessary? Why is the file that has clearly been written to being read as blank until it is reopened after being read as blank at least once?
When you read or write to a file, there's an internal pointer called a "cursor" that keeps track of where in the file you currently are. When you write a file, the cursor is set to the point after the last byte you wrote, so that if you perform additional writes, they happen after your previous write (rather than on top of it). When you perform a read, you are reading from the current position to the end of the file, which contains...nothing!
You can open a file (cursor position 0), then write the string "Hello" (cursor position 6), and attempting to read from the cursor will cause Ruby to say "Oh hey, there's no more content in this file past cursor position 6", and will simply return a blank string.
You can rewind the file cursor with IO#rewind to reset the cursor to the beginning of the file. You may then read the file (which will read from the cursor to the end of the file) normally.
Note that if you perform any writes after rewinding, you will overwrite your previously-written content.
# Unpacks first argument to 'filename'
filename = ARGV.first
# Lets write try writing to a file
write_txt = File.new(filename, 'w+')
write_txt.write("OMG I wrote this file!\nHow cool is that?")
write_txt.rewind
puts write_txt.read()
Note, however, that it is generally considered bad practice to both read from and write to the same file handle. You would generally open one file handle for reading and one for writing, as mixing the two can have nasty consequenses (such as accidentally overwriting existing content by rewinding the cursor for a read, and then performing a write!)
The output is not necessarily written to the file immediately. Also, the pointer is at the end of the file, if you want to read while in read-write mode you have to reset it. You can simply close if you want to reopen it for reading. Try:
write_txt.write("OMG I wrote this file!\nHow cool is that?")
# This outputs a blank line THIS IS THE LINE IN QUESTION
write_txt.close
txt = File.open(filename)
puts txt.read()
puts statement in ruby automatically adds a new line, how do I avoid it?
Use print instead.
You may want to follow it up by STDOUT.flush.
Also, you'll need to append "\r" at end of line to indicate "carriage return" and do next print at beginning of current line
$stdout.sync = true
100.times do
print "."
sleep 1
end
"How can I use “puts” to the console without a line break in ruby on rails?"
I've run command line programs that output a line, and then update that line a moment later. But with ruby I can only seem to output a line and then another line.
What I have being output now:
Downloading file:
11MB 294K/s
12MB 307K/s
14MB 294K/s
15MB 301K/s
16MB 300K/s
Done!
And instead, I want to see this:
Downloading file:
11MB 294K/s
Followed a moment later by this:
Downloading file:
16MB 300K/s
Done!
The line my ruby script outputs that shows the downloaded filesize and transfer speed would be overwritten each time instead of listing the updated values as a whole new line.
I'm currently using puts to generate output, which clearly isn't designed for this case. Is there a different output method that can achieve this result?
Use \r to move the cursor to the beginning of the line. And you should not be using puts as it adds \n, use print instead. Like this:
print "11MB 294K/s"
print "\r"
print "12MB 307K/s"
One thing to keep in mind though: \r doesn't delete anything, it just moves the cursor back, so you would need to pad the output with spaces to overwrite the previous output (in case it was longer).
By default when \n is printed to the standard output the buffer is flushed. Now you might need to use STDOUT.flush after print to make sure the text get printed right away.
I'm trying to read data from a text file and join it with a post string. When there's only one line in the file, it works fine. But with 2 lines, my request is failed. Is each_line reading the line break? How can I correct it?
File.open('sfzh.txt','r'){|f|
f.each_line{|row|
send(row)
}
I did bypass this issue with split and extra delimiter. But it just looks ugly.
Yes, each_line includes line breaks. But you can strip them easily using chomp:
File.foreach('test1.rb') do |line|
send line.chomp
end
Another way is to map strip onto each line as it is returned. To read a file line-by-line, stripping whitespace and do something with each line you can do the following:
File.open("path to file").readlines.map(&:strip).each do |line|
(do something with line)
end