Write Out Then Read In Hash of Two-element Arrays

Kind All,

I wonder if one of you knowledgeble folks can steer me in he right
direction:

I’m trying to get a hash I’ve created read back in after after writing
it out to a file, so that it is exactly the same afterward. The hash
has zero-based integer keys and two-element array values.

After I create and populate the hash:
Length of histHash after creation = 5

When I write out the hash, the output to STDOUT looks like this:
Write histHash[0] = 101
Write histHash[1] = 112
Write histHash[2] = 123
Write histHash[3] = 134
Write histHash[4] = 145
5 histHash lines written
histHash written = 01011112212331344145

After I delete the elements of the hash:
Length of histHash after deletion = 0

But when I read it back in, it looks like this:
Read histHash[0] = 10; line = 10
Read histHash[1] = 1; line = 1
Read histHash[2] = 11; line = 11
Read histHash[3] = 2; line = 2
Read histHash[4] = 12; line = 12
Read histHash[5] = 3; line = 3
Read histHash[6] = 13; line = 13
Read histHash[7] = 4; line = 4
Read histHash[8] = 14; line = 14
Read histHash[9] = 5; line = 5
10 histHash lines read
histHash read = 5301061311742118143295412
Length of histHash after read = 10

As you can see, it’s length is five lines when I initially write it to
the file, but ten lines when I read it back in. I’ve been pawing though
the docs, but I can’t figure out what I’m doing wrong. Any help will be
greatly appreciated.

Here is the errant code:

write out and then read in hash of two-element arrays

create and populate the hash

histHash = Hash.new
histHash[0] = [10, 1]
histHash[1] = [11, 2]
histHash[2] = [12, 3]
histHash[3] = [13, 4]
histHash[4] = [14, 5]
puts
puts “Length of histHash after creation = #{histHash.length}”
puts

write the hash to the file

fileOut = File.new(“savedHash.sdo”, “w”)
histHash.length.times do |i|
fileOut.puts(histHash[i])
puts “Write histHash[#{i}] = #{histHash[i]}”
end
fileOut.close

puts “#{histHash.length} histHash lines written”
puts “histHash written = #{histHash}”
puts

Delete the hist hash elements

histHash.length.times do |i|
histHash.delete(i)
end
puts “Length of histHash after deletion = #{histHash.length}”
puts

load (read) the saved file

fileIn = File.new(“savedHash.sdo”, “r”)
i = 0
fileIn.each_line{|line|histHash[i]=[line.to_i]; puts “Read
histHash[#{i}] = #{histHash[i]}; line = #{line}”;i+=1}
fileIn.close
puts “#{histHash.length} histHash lines read”
puts “histHash read = #{histHash}”
puts “Length of histHash after read = #{histHash.length}”
puts

David,

My initial guess:

puts “Write histHash[#{i}] = #{histHash[i]}”

replaced with

fileOut.print("#{histHash[i]}\n")

This is what you want?

HTH,
Peter

Sorry,

fileOut.puts(histHash[i])

should be replaced with

fileOut.print("#{histHash[i]}\n")

Cheers,
Peter

Instead of writing your own de/serialization code why not give
Marshal.dump and Marshal.load a try:

dumped_histHash = Marshal.dump(histHash)
=>
“\004\010{\ni\000[\ai\017i\006i\006[\ai\020i\ai\a[\ai\021i\010i\010[\ai\022i
ti\t[\ai\023i\n”

loaded_histHash = Marshal.load(dumped_histHash)
=> {0=>[10, 1], 1=>[11, 2], 2=>[12, 3], 3=>[13, 4], 4=>[14, 5]}

If you need a human readable/editable file consider using YAML:

require ‘yaml’
=> true

puts yaml_histHash = histHash.to_yaml


0:

  • 10
  • 1
    1:
  • 11
  • 2
    2:
  • 12
  • 3
    3:
  • 13
  • 4
    4:
  • 14
  • 5
    => nil

loaded_histHash = YAML.load(yaml_histHash)
=> {0=>[10, 1], 1=>[11, 2], 2=>[12, 3], 3=>[13, 4], 4=>[14, 5]}

Farrel

Farrel L. wrote:

Instead of writing your own de/serialization code why not give
Marshal.dump and Marshal.load a try:

dumped_histHash = Marshal.dump(histHash)
=>
“\004\010{\ni\000[\ai\017i\006i\006[\ai\020i\ai\a[\ai\021i\010i\010[\ai\022i
ti\t[\ai\023i\n”

loaded_histHash = Marshal.load(dumped_histHash)
=> {0=>[10, 1], 1=>[11, 2], 2=>[12, 3], 3=>[13, 4], 4=>[14, 5]}

If you need a human readable/editable file consider using YAML:

require ‘yaml’
=> true

puts yaml_histHash = histHash.to_yaml


0:

  • 10
  • 1
    1:
  • 11
  • 2
    2:
  • 12
  • 3
    3:
  • 13
  • 4
    4:
  • 14
  • 5
    => nil

loaded_histHash = YAML.load(yaml_histHash)
=> {0=>[10, 1], 1=>[11, 2], 2=>[12, 3], 3=>[13, 4], 4=>[14, 5]}

Farrel

Farrel,

Good suggestion. Had I not forgotten about marshal and yaml (after
having read about it a while back in the pickaxe book), I would have
done so initally. At any rate, thank you for the suggestion. And for
jogging my memory!

David

Peter S. wrote:

David,

My initial guess:

puts “Write histHash[#{i}] = #{histHash[i]}”

replaced with

fileOut.print("#{histHash[i]}\n")

This is what you want?

HTH,
Peter

Peter,

After a number of suggestions from gracious Rubyists, I am happy to say
that I am now all set. Thank you very much for your help. Best
regards,

David

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs