Beginner: Read file

J

Justin To

report = File.open('ReportTxt.txt', 'r') do |L|
while line = L.gets

report.getc.chr

end
end



I'm quite lost...what I'm trying to do is read a file character by
character
until I've read every character.

Thanks in advance!
 
E

Eric I.

report = File.open('ReportTxt.txt', 'r') do |L|
   while line = L.gets

  report.getc.chr

    end
end

I'm quite lost...what I'm trying to do is read a file character by
character
until I've read every character.

Hi Justin,

A couple of things. You've combined two distinct ways of using the
call to open. You either capture the return value and use that to
read and close the file, *OR* you provide a block with the IO variable
a reference to the file. In the latter case, when you reach the end
of the block, the file is closed automatically.

Second, the variable "L" is a constant. I'm not sure you want a
constant.

Below are two bits of code that do what you're trying to do, each
using one of the distinct ways to use the open call.

====

File.open('ReportTxt.txt', 'r') do |l|
while c = l.getc
puts c.chr
end
end


l = File.open('ReportTxt.txt', 'r')
while c = l.getc
puts c.chr
end
l.close

====

Do you mind my asking what resource(s) you're using to learn Ruby?

I hope that helps,

Eric

====

LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE
workshops.
Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.
Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.
Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.
Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich
Please visit http://LearnRuby.com for all the details.
 
S

Stefano Crocco

report =3D File.open('ReportTxt.txt', 'r') do |L|
=C2=A0 =C2=A0while line =3D L.gets

=C2=A0 report.getc.chr

=C2=A0 =C2=A0 end
end

There are at least two problems with your code:
1) you use the variable report in the block, but the variable is assigned a=
=20
value *after* the File.open method returns. This means that when you call=20
report.getc inside your block, report is nil, hence the error you're gettin=
g=20
(by the way, when you ask for help, you should specify what kind of error=20
you're getting).
2) You use L.gets to iterate. But: a) gets, with no argument, iterates=20
linewise, which means you'll read a character for each line; b) gets moves =
the=20
position in the file, which means that, after L.gets reads the last line of=
=20
the file, you'll get an error.

To achieve what you want, you can use the following code (by the way, capit=
al=20
letters in ruby are used for constants, so it's better not to use them for=
=20
block variables):

=46ile.open('ReportTxt.txt', 'r') do |f|
until f.eof?
f.getc.chr
end
end

I hope this helps

Stefano
 
M

Michael Linfield

I'm quite lost...what I'm trying to do is read a file character by
character
until I've read every character.

Thanks in advance!

Posting 'Beginner:' doesn't merit anything special :)

Here is one way of doing it.

File.open("myfile") do |file|
file.each_byte {|x| puts x}
end

The value of 'x' will be in ascii, I'll let you figure out how to
translate ascii back into text :)

- Mac
 
J

Justin To

Hi Eric,

Thanks so much for your help. I'm reading O'Reilly Ruby Cookbook, which
I have found rather difficult to learn from. I'm also reading a free
tutorial online at rubylearning.com. Neither provide enough
clarification for me as I am new to Ruby.

Also, I'm very confused on the regular expressions:

Problem: I want to have a file that has information, for instance,
Version #, Part #
v.1.0-A, 000000
v.1.0-A, 000000

Now I want to store each character that's not a 'v', '.', or '-' as one
string in one array called version (so element one should read "10A").
Then I want to say, "Ok I'm at a comma now, so I want to store the
following information in the next array"... so I want to store the whole
part# as one element of an array, called part (element one should read
"000000"). Then... I want to say, "Ok, I'm at a newline, so start the
same process again"

basically, i want to compare if two lines have the same version# or
part#
so in this case, i want to check if version[0] == version[1], which
should return true. ("10A"=="10A")

Probably a very confusing explanation, but if you can help that'd be
great. I'm trying to learn by doing some examples like this, but it's
very difficult =(

Thanks again!!
 
D

David Masover

File.open("myfile") do |file|
file.each_byte {|x| puts x}
end

The value of 'x' will be in ascii, I'll let you figure out how to
translate ascii back into text :)

I believe that's why each_byte is depricated -- each_char will read each
character, even when a character is more than a byte.
 
E

Eric I.

Thanks so much for your help. I'm reading O'Reilly Ruby Cookbook, which
I have found rather difficult to learn from. I'm also reading a free
tutorial online at rubylearning.com. Neither provide enough
clarification for me as I am new to Ruby.

Given your previous posting on procs and the code you submitted here,
I got the sense that you were jumping to some advanced topics before
having a good sense for the basics. And that's why I asked about the
resources you were using; something didn't seem quite right.

A cookbook is designed to give you solutions to real-world, practical,
common problems, and the authors are not obligated to cover the
basics. So for most people, they aren't the best resource to learn
the language (but they can be invaluable at a later stage). And I
don't know much about that web site.

What languages do you already know?
Also, I'm very confused on the regular expressions:

Problem: I want to have a file that has information, for instance,
 Version #, Part #
 v.1.0-A,   000000
 v.1.0-A,   000000

Now I want to store each character that's not a 'v', '.', or '-' as one
string in one array called version (so element one should read "10A").
Then I want to say, "Ok I'm at a comma now, so I want to store the
following information in the next array"... so I want to store the whole
part# as one element of an array, called part (element one should read
"000000"). Then... I want to say, "Ok, I'm at a newline, so start the
same process again"

basically, i want to compare if two lines have the same version# or
part#
so in this case, i want to check if version[0] == version[1], which
should return true. ("10A"=="10A")

Probably a very confusing explanation, but if you can help that'd be
great. I'm trying to learn by doing some examples like this, but it's
very difficult =(

Parsing your file character by character would be a very complicated
way to do it. There are two common ways to approach it. Both involve
reading the data line by line (rather than character by character)
since a line equates to a record for you.

The first way would be to use String#split to break apart the version
and part numbers and then to use String#gsub to remove the unwanted
characters.

The second way would be to use a regular expression with grouping
parentheses to pull out the desired data. You could do a String#gsub
to further process a piece of data to get rid of unwanted characters,
although it's unclear to me why it's more desirable to have "10A"
rather than "1.0-A".

Also, if you want to look for duplicates, storing the data in an Array
will likely lead to O(n**2) operation. If you have lots of data, that
can be inefficient. You may want to consider the Set class in the
'set' library, or alternatively using one or two Hashes keyed on the
data you want to check for duplicates.

Eric

====

LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE
workshops.
Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.
Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.
Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.
Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich
Please visit http://LearnRuby.com for all the details.
 
E

Eric I.

I believe that's why each_byte is depricated -- each_char will read each
character, even when a character is more than a byte.

Well, unless I'm mistaken....

Ruby 1.8.6 has IO#each_byte but not IO#each_char.

Ruby 1.8.7 and 1.9 have both IO#each_byte and IO#each_char, but
neither deprecates IO#each_byte since it's still useful for processing
byte-oriented (i.e., binary) files/streams.

Eric

====

LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE
workshops.
Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.
Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.
Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.
Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich
Please visit http://LearnRuby.com for all the details.
 
D

David Masover

Ruby 1.8.7 and 1.9 have both IO#each_byte and IO#each_char, but
neither deprecates IO#each_byte since it's still useful for processing
byte-oriented (i.e., binary) files/streams.

Absolutely... I should have been more specific. It certainly is depricated for
reading strings.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top