Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read/write objects to a file?

I would like to write an object (a simple collection) to a file. I've been looking around and found this question and this question. I also went through a lot of sites with broken links etc, but I don't seem to be able to find a way to write to a file in smalltalk. I tried this (and other things, but they come down to the same):

out := 'newFile' asFileName writeStream.
d associationsDo: [ :assoc | out 
    nextPutAll: assoc key asString;
    nextPut: $, ;
    nextPutAll: assoc value asString; cr. ]
out close.

as suggested in the linked questions, but it does not seem to be doing anything. It does not throw errors, but I don't find any files either.

The only thing I want to do is persist my object (binary or textual does not really matter), so how could I do this?

Thanks in advance

like image 540
Mr Tsjolder Avatar asked Dec 15 '22 09:12

Mr Tsjolder


2 Answers

What you are doing is creating a write stream on a string. That actually works but the information is stored on a string object, no files will be written.

This works in both Squeak and Pharo (and probably other dialects):

FileStream
    forceNewFileNamed: 'filename.ext'
    do: [ :stream |
         d associationsDo: [ :assoc |
             stream
                 ascii; "data is text, not binary"
                 nextPutAll: assoc key asString;
                 nextPut: $, ;
                 nextPutAll: assoc value asString;
                 cr ] ].

In Pharo you could write:

'filename.ext' asFileReference writeStreamDo: [ :stream |
    ... ].

Note however that there are better ways to store structured data in files, e.g. STON (Smalltalk Object Notation, Smalltalk version of JSON) or XML. If you want to persist objects than you might want to checkout Fuel, StOMP (probably no longer supported) or any of the other object serializers.

Lastly there's also ImageSegment, a VM based object serializer (no extra packages needed), but you'll probably need some help with that.

like image 56
Max Leske Avatar answered Dec 16 '22 22:12

Max Leske


The traditional Smalltalk serialization format uses the storeOn: and readFrom: methods. E.g.

d1 := {'a'->1. 'b'->2. 'c'->'3'} as: Dictionary.

"store"
FileStream forceNewFileNamed: 'mydict.st' do: [:out | d1 storeOn: out].

"read"
d2 := FileStream oldFileNamed: 'mydict.st' do:  [:in | Object readFrom: in].

This is a textual format and gets inefficient for larger data sets. Also, it cannot store cyclical references. For that, check out the more advanced serialization options as listed in the other answers.

like image 43
Vanessa Freudenberg Avatar answered Dec 16 '22 21:12

Vanessa Freudenberg