How to write to file when using Marshal::dump in Ruby for object serialization
Asked Answered
S

1

5

Lets say I have the object line from class Line:

class Line
  def initialize point1, point2
    @p1 = point1
    @p2 = point2
  end
end

line = Line.new...

How can I binary serialize the line object? I tried with:

data = Marshal::dump(line, "path/to/still/unexisting/file")

but it created file and didn't add anything. I read the Class: IO documentation but I couldn't really get it.

Selfopinionated answered 2/2, 2014 at 21:31 Comment(2)
Marshal isn't a good choice for persistent storage, the binary format depends on the specific Ruby version you're using. You're better off using a generic format like JSON, YAML, XML, ...Phyla
@muistooshort it's a great choice if you are comfortable with recreating it if the ruby version changes, and you have lots of data/vars that you need saved. It's also pretty fast.Lubricity
H
11

Like this:

class Line
  attr_reader :p1, :p2
  def initialize point1, point2
    @p1 = point1
    @p2 = point2
  end
end

line = Line.new([1,2], [3,4])

Save line:

FNAME = 'my_file'

File.open(FNAME, 'wb') {|f| f.write(Marshal.dump(line))}

Retrieve into line1:

line1 = Marshal.load(File.binread(FNAME))

Confirm it works:

line1.p1 # => [1, 2]
Henna answered 3/2, 2014 at 6:8 Comment(2)
Why File.open(FNAME, 'wb') {|f| f.write(Marshal.dump(line))} works well, but using f = File.open(FNAME, 'wb') and f.write(Marshal.dump(line)) causes 'marshal data too short (ArgumentError)' when loading?Overstride
@KaRolthas, interesting question. The answer is that when open is used with a block the file is closed after the block is executed. When open does not have a block you need to close the file (f.close) after writing. If you don't close the file File.binread(FNAME) attempts to read an open file, causing the error.Henna

© 2022 - 2024 — McMap. All rights reserved.