On 8-May-09, at 3:32 PM, Claude Marinier wrote:
Greetings,
I have been building a library catalogue application in Gambit-C. It can import CSV, build indexes, and perform searches. It is now time to think about storing this in a file. Does the write function produce output which can be used to recreate the data structures I saved? If yes, how is this done?
You can do that using binary serialization (preferred because it is more compact) or textual serialization (useful for debugging because it is somewhat humanly readable). Check the sample code below.
Marc
;; Method #1 (uses binary serialization)
(define (save1 obj filename) (call-with-output-file filename (lambda (p) (let ((v (object->u8vector obj))) (write-subu8vector v 0 (u8vector-length v) p)))))
(define (restore1 filename) (let ((size (file-size filename))) (call-with-input-file filename (lambda (p) (let ((v (make-u8vector size))) (if (not (= size (read-subu8vector v 0 size p))) (error "file size inconsistency") (u8vector->object v)))))))
;; Method #2 (uses textual serialization)
(define (save2 obj filename) (call-with-output-file filename (lambda (p) (output-port-readtable-set! p (readtable-sharing-allowed?-set (output-port-readtable p) 'serialize)) (write obj p))))
(define (restore2 filename) (call-with-input-file filename (lambda (p) (input-port-readtable-set! p (readtable-sharing-allowed?-set (input-port-readtable p) 'serialize)) (read p))))
;; Test by creating a database and saving/restoring it both ways. ;; The database contains cycles. So this test shows that ;; saving/restoring preserves sharing and cycles.
(define-type person id: 99d2e11d-a556-46c6-a468-c4fa546114fc ;; required for serialization name children unprintable: parent)
(define a (make-person "alice" '() #f)) (define b (make-person "bob" '() #f)) (define c (make-person "chuck" (list a b) #f))
(person-parent-set! a c) (person-parent-set! b c)
(define db (list (cons "alice" a) (cons "bob" b) (cons "chuck" c)))
(define (get db key) (cdr (assoc key db)))
;; save/restore using both methods and check that all is well
;; method #1
(save1 db "db1.bin") (define db1 (restore1 "db1.bin"))
(pp (person-children (get db1 "chuck")))
(pp (eq? (person-parent (get db1 "alice")) (get db1 "chuck")))
;; method #2
(save2 db "db2.txt") (define db2 (restore2 "db2.txt"))
(pp (person-children (get db2 "chuck")))
(pp (eq? (person-parent (get db2 "alice")) (get db2 "chuck")))
;; output: ;; ;; (#<person #2 name: "alice" children: ()> ;; #<person #3 name: "bob" children: ()>) ;; #t ;; (#<person #4 name: "alice" children: ()> ;; #<person #5 name: "bob" children: ()>) ;; #t