如何将read/write对象写入文件?

How to read/write objects to a file?

我想将一个对象(一个简单的集合)写入一个文件。我一直在四处寻找并找到 this question and this question。我还浏览了很多链接断开等的站点,但我似乎无法找到在 smalltalk 中写入文件的方法。我试过这个(和其他东西,但它们归结为相同):

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

如链接问题中所建议的那样,但它似乎没有做任何事情。它不会抛出错误,但我也找不到任何文件。

我唯一想做的就是保留我的对象(二进制或文本并不重要),那么我该怎么做呢?

提前致谢

看来您使用的是扩展语法,而不是基础语法。 至少在 Pharo 中,'newFile' asFileName 是一个字符串,而#writeStream 为您提供了同一字符串上的流,而不是文件上的流。

试试 FileStream newFileNamed: 'newFile' 或类似的东西。

最重要的是:当发生奇怪的事情时,请检查。检查部分评估并检查您的所有假设。或者更好的是,调试并查看代码的去向。

您正在做的是在字符串上创建写入流。这确实有效,但信息存储在字符串对象中,不会写入任何文件。

这适用于 Squeak 和 Pharo(可能还有其他方言):

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 ] ].

在 Pharo 中你可以这样写:

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

但是请注意,有更好的方法可以将结构化数据存储在文件中,例如STON (Smalltalk Object Notation, Smalltalk version of JSON) or XML. If you want to persist objects than you might want to checkout Fuel, StOMP(可能不再受支持)或任何其他对象序列化程序。

最后还有 ImageSegment,一个基于 VM 的对象序列化程序(不需要额外的包),但您可能需要一些帮助。

解决方案:

| d out | 
d := Dictionary new.
d at: 'green' put: 'vert'.
d at: 'blue' put: 'bleu'. 
d at: 'red' put: 'rouge'.
d at: 'white' put: 'blanc'.

out := FileStream fileNamed: 'dict-out.txt'.

d associationsDo: [ :assoc | out 
    nextPutAll: assoc key asString;
    nextPut: $, ;
    nextPutAll: assoc value asString; cr.].
out close.

另请参阅:

传统的Smalltalk序列化格式使用storeOn:readFrom:方法。例如

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].

这是一种文本格式,对于较大的数据集来说效率很低。此外,它不能存储循环引用。为此,请查看其他答案中列出的更高级的序列化选项。

燃料中的等价物是

FLSerializer serialize: d toFileNamed: 'filename.ext'.

d := FLMaterializer materializeFromFileNamed: 'filename.ext'