
-----------------------------------
wtd
Fri Jul 16, 2004 10:08 pm

[Ruby-tut] Practical example: File I/O (and odds and ends)
-----------------------------------
File I/O seems to be a popular topic in other language forums here, so I thought I'd write up a quick tutorial on doing it in Ruby.

The first step will be getting a File object for the file we want to read.  There are a few possible methods of doing this.  Firstly, we can create a File object in the same way any other object is created, by using the File class' new method.

For these examples, we'll use the input file "infile.txt" and the output file "outfile.dat".

my_file = File.new("infile.txt", "r")

The "r" indicates the mode the file is being opened in.  In this case, read-only.  Other possibilities are "w", "rw", and "b" indicates binary.  Binary cannot be used with "rw".

Alternatively, the File class has an "open" class method.

my_file = File.open("infile.txt", "r")

But this all very boring, so let's approach this with a problem in mind.  We have a file that looks like:

Chris | aa | com | 3 | 9
Bob | bb | net | 1 | 16
Joe | ccccc | edu | 5 | 27
Chris | wooble | org | 6 | 3

The first column very simply contains a customer's name.  The second is the domain you're hosting for them.  The third is the top level domain tha domain is in.  The fourth is the number of years they're signed for, and the fifth is how much they pay per year.

The output should look like:

Chris owes us {some amount} over the next {so many} years for the domains {such and such}.

Step 1: Open the input file.

input_file = File.open("customer_data.txt", "r")

Step 2: Get the contents of the file, then close the input file.

contents = input_file.readlines
input_file.close

Step 3: Split each line on the delimiter of "|", into at most 5 columns.

contents.collect! { |line| line.split(/\s*\|\s*/, 5) }

Step 4: Create an associative array (Hash) which will hold info about each customer.

customers = {}

Step 5: Iterate through the contents of the file.  For each user, if they're already in the customers hash, add the domain and add its cost to their total, as well as the number of years they're signed for.

contents.each do |line|
   customer_name = line[0]
   customer_domain = "#{line[1]}.#{line[2]}"
   customer_rate = line[3].to_i
   customer_duration = line[4].to_i
   customer_cost = customer_rate * customer_duration

   unless customers.has_key? customer_name
      customers[customer_name] = {"domains" => [], "cost" => 0, "duration" => 0}
   end

   customers[customer_name]["domains"]  [], "cost" => 0, "duration" => 0}

   customers[customer_name]["domains"]  [], "cost" => 0, "duration" => 0}

   customers[customer_name]["domains"] 