# Beginner: Read file

**URL:** https://rubytalk.org/t/beginner-read-file/46909
**Category:** ruby-talk
**Created:** [4 June 2008 17:08 UTC](https://rubytalk.org/t/beginner-read-file/46909 "2008-06-04T17:08:09Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Justin\_To](https://avatars.discourse-cdn.com/v4/letter/j/22d042/32.png) [@Justin\_To](https://rubytalk.org/u/Justin_To)
#### Post date: [4 June 2008 17:08 UTC](https://rubytalk.org/t/beginner-read-file/46909/1 "2008-06-04T17:08:09Z")

</div>

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

&nbsp;&nbsp;report.getc.chr

&nbsp;&nbsp;&nbsp;&nbsp;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!

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![Eric\_I2](https://avatars.discourse-cdn.com/v4/letter/e/22d042/32.png) [@Eric\_I2](https://rubytalk.org/u/Eric_I2)
#### Post date: [4 June 2008 17:24 UTC](https://rubytalk.org/t/beginner-read-file/46909/2 "2008-06-04T17:24:12Z")

</div>

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.

> **···**
>
> On Jun 4, 1:08 pm, Justin To \<te...@hotmail.com\> wrote:
> 
> > 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.
> 
> ====
> 
> File.open('ReportTxt.txt', 'r') do |l|  
> &nbsp;&nbsp;while c = l.getc  
> &nbsp;&nbsp;&nbsp;&nbsp;puts c.chr  
> &nbsp;&nbsp;end  
> end
> 
> l = File.open('ReportTxt.txt', 'r')  
> while c = l.getc  
> &nbsp;&nbsp;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.  
> &nbsp;&nbsp;&nbsp;Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich  
> Please visit [http://LearnRuby.com](http://LearnRuby.com) for all the details.

---

<div class="post-metadata">

### Author: ![Stefano\_Crocco](https://avatars.discourse-cdn.com/v4/letter/s/5f9b8f/32.png) [@Stefano\_Crocco](https://rubytalk.org/u/Stefano_Crocco)
#### Post date: [4 June 2008 17:26 UTC](https://rubytalk.org/t/beginner-read-file/46909/3 "2008-06-04T17:26:38Z")

</div>

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

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

File.open('ReportTxt.txt', 'r') do |f|  
&nbsp;&nbsp;until f.eof?  
&nbsp;&nbsp;&nbsp;&nbsp;f.getc.chr  
&nbsp;&nbsp;end  
end

I hope this helps

Stefano

> **···**
>
> On Wednesday 04 June 2008, Justin To wrote:
> 
> > report = File.open('ReportTxt.txt', 'r') do |L|  
> > while line = L.gets
> > 
> > report.getc.chr
> > 
> > ```
> > end
> > 
> > ```
> > 
> > end

---

<div class="post-metadata">

### Author: ![Jon\_Hawkins](https://avatars.discourse-cdn.com/v4/letter/j/958977/32.png) [@Jon\_Hawkins](https://rubytalk.org/u/Jon_Hawkins)
#### Post date: [4 June 2008 17:31 UTC](https://rubytalk.org/t/beginner-read-file/46909/4 "2008-06-04T17:31:58Z")

</div>

> 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

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

### Author: ![Justin\_To](https://avatars.discourse-cdn.com/v4/letter/j/22d042/32.png) [@Justin\_To](https://rubytalk.org/u/Justin_To)
#### Post date: [4 June 2008 17:43 UTC](https://rubytalk.org/t/beginner-read-file/46909/5 "2008-06-04T17:43:26Z")

</div>

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](http://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!!

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

### Author: ![David\_Masover](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Masover](https://rubytalk.org/u/David_Masover)
#### Post date: [4 June 2008 18:25 UTC](https://rubytalk.org/t/beginner-read-file/46909/6 "2008-06-04T18:25:13Z")

</div>

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

> **···**
>
> On Wednesday 04 June 2008 12:31:58 Michael Linfield wrote:
> 
> > 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 🙂

---

<div class="post-metadata">

### Author: ![Eric\_I2](https://avatars.discourse-cdn.com/v4/letter/e/22d042/32.png) [@Eric\_I2](https://rubytalk.org/u/Eric_I2)
#### Post date: [4 June 2008 18:39 UTC](https://rubytalk.org/t/beginner-read-file/46909/7 "2008-06-04T18:39:15Z")

</div>

> 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

> **···**
>
> On Jun 4, 1:43 pm, Justin To \<te...@hotmail.com\> wrote:
> 
> ====
> 
> LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE  
> workshops.  
> &nbsp;&nbsp;&nbsp;Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich  
> Please visit [http://LearnRuby.com](http://LearnRuby.com) for all the details.

---

<div class="post-metadata">

### Author: ![Eric\_I2](https://avatars.discourse-cdn.com/v4/letter/e/22d042/32.png) [@Eric\_I2](https://rubytalk.org/u/Eric_I2)
#### Post date: [4 June 2008 21:19 UTC](https://rubytalk.org/t/beginner-read-file/46909/8 "2008-06-04T21:19:38Z")

</div>

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

> **···**
>
> On Jun 4, 2:25 pm, David Masover \<ni...@slaphack.com\> wrote:
> 
> > On Wednesday 04 June 2008 12:31:58 Michael Linfield wrote:
> > 
> > \> 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.
> 
> ====
> 
> LearnRuby.com offers Rails & Ruby HANDS-ON public & ON-SITE  
> workshops.  
> &nbsp;&nbsp;&nbsp;Ruby Fundamentals Wkshp June 16-18 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ready for Rails Ruby Wkshp June 23-24 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby on Rails Wkshp June 25-27 Ann Arbor, Mich.  
> &nbsp;&nbsp;&nbsp;Ruby Plus Rails Combo Wkshp June 23-27 Ann Arbor, Mich  
> Please visit [http://LearnRuby.com](http://LearnRuby.com) for all the details.

---

<div class="post-metadata">

### Author: ![David\_Masover](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Masover](https://rubytalk.org/u/David_Masover)
#### Post date: [4 June 2008 21:45 UTC](https://rubytalk.org/t/beginner-read-file/46909/9 "2008-06-04T21:45:19Z")

</div>

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

> **···**
>
> On Wednesday 04 June 2008 16:19:38 Eric I. wrote:
> 
> > 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.
