Description Usage Arguments Details Value Note Examples
This version of readRDS and saveRDS provides capabilities to define serializers for non-native R objects (such as external pointers to C structures).
1 2 3 |
object |
ANY. The R object to serialize to a file. This object should
have an attribute with the name "RDS2.serialize" if the RDS2 package
capabilities for serializing and deserializing non-native R objects
wish to be used. It should consist of a list with one or both of the
keys If the "RDS2.serialize" attribute has the list element
|
... |
arguments to pass to |
file |
a connection or the name of the file where the R object is saved to or read from. |
The function behaves exactly the same as saveRDS
for native R objects. However, if the object has an attribute
called "RDS2.serialize", this will be used to serialize the object
instead. Specifically, the attribute must be a list with keys
"read"
and "write"
which must be functions that
transform the object into a vanilla R object.
For example, suppose we have an object a <- list(x = 1, y = z)
,
where z
is an external pointer to a C structure.
We could set the "RDS2.serialize" attribute as follows.
attr(a, "RDS2.serialize") <- list(
read = function(obj) { obj$y <- raw_to_ptr(obj$y); obj },
write = function(obj) { obj$y <- ptr_to_raw(obj$y); obj }
)
Here, raw_to_ptr
and ptr_to_raw
are helper functions
that serialize and deserialize the C structure to an R object,
such as a raw
vector.
For readRDS
, an R object. For saveRDS
, NULL
,
invisibly.
The attribute "RDS2.serialize" will be serialized along with the
object, so you must be careful that the parent environment chain of
helper functions used in the read and write methods do not contain
large objects. In general, it is better to use no helper functions
(i.e., the read
and write
functions should be pure
functions rather than closures, and you should set their
environment(read) <- globalenv()
explicitly.).
The mechanism provided by RDS2 is slightly different than the
refhook
argument to the base readRDS
and
saveRDS
, since it encloses the serialization procedure
within the serialized object. This allows for greater portability, since
(if these functions are pure) the consumer of an RDS2-serialized object
need only have the RDS2 package attached, rather than the function or
library the refhook
may be from.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | file <- tempfile()
native_obj <- list(x = 1)
saveRDS(native_obj, file)
stopifnot(identical(native_obj, readRDS(file)))
# We do not have any C structures to play with, but we will pretend
# by converting the string "pointer" to a raw vector.
nonnative_obj <- list(x = 1, y = "pointer")
attr(nonnative_obj, "RDS2.serialize") <- list(
read = function(obj) { obj$y <- rawToChar(obj$y); obj },
write = function(obj) { obj$y <- charToRaw(obj$y); obj }
)
saveRDS(nonnative_obj, file)
without_attributes <- function(obj) { attr(obj, "RDS2.serialize") <- NULL; obj }
stopifnot(identical(list(x = 1, y = charToRaw("pointer")),
without_attributes(base::readRDS(file))))
stopifnot(all.equal(nonnative_obj, readRDS(file)))
# Without RDS2, the vanilla object that was passed through the "write" method
# is stored in the file. We cannot load the object correctly unless RDS2
# is in the search path, so consumers of this RDS file should be careful.
# With RDS, the object is deserialized correctly.
|
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.