What Is an Eoferror in Ruby File I/O

What is an EOFError in Ruby file I/O?

EOFError is handy in all of IO, the class which is the basis of all input/output in ruby. Now also remember core Unix concepts: everything is a file. This includes sockets. So, if you have some socket open and are reading from it, an exceptional condition might be to encounter an end of file.

All the examples out there show trivial uses of EOFError (while reading some text file), which are not really useful. However, start digging through net/http or other classes which use sockets heavily, and you'll see this exception being used.

Edited to add this example from net/ftp

def getline
line = @sock.readline # if get EOF, raise EOFError
line.sub!(/(\r\n|\n|\r)\z/n, "")
if @debug_mode
print "get: ", sanitize(line), "\n"
end
return line
end

How do I avoid EOFError with Ruby script?

The way you are writing your file isn't idiomatic Ruby. This should work better:

(1..100).each do |num|
page = open('SOMEURL' + num, :proxy => proxy_uri).read
pattern = "<img"
tags = page.scan(pattern)
output << tags.length
end

File.open("outputlist.txt", 'a') do |fo|
fo.puts output
end

I suspect that the file is being closed because it's been opened, then not written-to while 100 pages are processed. If that takes a while I can see why they'd close it to avoid apps using up all the file handles. Writing it the Ruby-way automatically closes the file immediately after the write, avoiding holding handles open artificially.

As a secondary thing, rather than use a simple pattern match to try to locate image tags, use a real HTML parser. There will be little difference in processing speed, but potentially more accuracy.

Replace:

page = open('SOMEURL' + num, :proxy => proxy_uri).read
pattern = "<img"
tags = page.scan(pattern)
output << tags.length

with:

require 'nokogiri'

doc = Nokogiri::HTML(open('SOMEURL' + num, :proxy => proxy_uri))
output << doc.search('img').size

Ruby mailer is coming up with an EOFError

Alright, thank you guys, I actually had malformed code in the UserMailer. The actual code I had in the from line had a <> encasing an email address and had the senders name on the outside. Though that has worked on some of the private email servers I have used/work on, it does not work on Hostmonster. Soo, for anyone that ends up using Hostmonster in the future, keep everything about your mailers configuration simple (the message can be complicated but the SMTP Config needs to be simple). Thanks.

chef-client run fails to sync cookbooks with EOFError: end of file reached

When chef-client starts up, one of the things it has to do is download the cookbook code it is going to use for the run. This is cached locally to speed future runs, but the first time or when files change etc etc. This exception is saying that it is failing while trying to download the ewe-powershell cookbook from the server. This possibly means it was corrupted during the upload process. A quick first check would be to knife cookbook delete that one and re-upload it. If that fails I would start trying to figure out what file is failing to download. If you turn up Chef's log level (-l debug) you should see which URL it is trying to get, which will tell you which file is failing. With that in hand, try curl'ing it directly from Bookshelf (the service with Chef Server that handles file upload and download).

Line-oriented streaming in Ruby (like grep)

It looks like your best bet is to use STDOUT.syswrite and STDOUT.sysread - the following seemed to have reasonably good performance, despite being ugly code:

STDIN.sync = true
STDOUT.syswrite "Looking for #{ARGV[0]}\n"

def next_line
mybuff = @overflow || ""
until mybuff[/\n/]
mybuff += STDIN.sysread(8)
end
overflow = mybuff.split("\n")
out, *others = overflow
@overflow = others.join("\n")
out
rescue EOFError => e
false # NB: There's a bug here, see below
end

line = next_line
while line
STDOUT.syswrite "#{line}\n" if line =~ /#{ARGV[0]}/i
line = next_line
end

Note: Not sure you need #sync with #sysread, but if so you should probably sync STDOUT too. Also, it reads 8 bytes at a time into mybuff - you should experiment with this value, it's highly inefficient / CPU heavy. Lastly, this code is hacky and needs a refactor, but it works - tested it using ls -l ~/* | ruby rgrep.rb doc (where 'doc' is the search term)


Second note: Apparently, I was so busy trying to get it to perform well, I failed to get it to perform correctly! As Dmitry Shevkoplyas has noted, if there is text in @overflow when EOFError is raised, that text will be lost. I believe if you replace the catch with the following, it should fix the problem:

rescue EOFError => e
return false unless @overflow && @overflow.length > 0
output = @overflow
@overflow = ""
output
end

(if you found that helpful, please upvote Dmitry's answer!)



Related Topics



Leave a reply



Submit