Update: of course write(io, ...)
does not work in general, because of padding. I made it work with reinterpret
and also unsafe_write
, but advice on whether I am really doing the right thing would be appreciated. Self-contained MWE below.
struct Record{T1, T2}
id::T1
ix::T2
date::Date
end
random_Date() = Date(rand(1900:2100), rand(1:12), rand(1:28))
random_record(T1, T2) = Record(rand(T1), rand(T2), random_Date())
T1 = Int16
T2 = Int8
path = "/tmp/test"
## random array
x = [random_record(T1, T2) for _ in 1:200]
############################################################
# write elementwise -- this DOES NOT WORK, because of padding
############################################################
@generated function write_struct(io, x)
@assert isbits(x)
if Base.isstructtype(x)
Expr(:block, [:(write_struct(io, x.$fn)) for fn in fieldnames(x)]...)
else
:(write(io, x))
end
end
io = open(path, "w")
for elt in x
write_struct(io, elt)
end
close(io)
## read
io = open(path, "r")
y = Mmap.mmap(io, Vector{Record{T1, T2}}, (length(x),))
x == y # false, because of:
sizeof(x[1]) # 11
sizeof(y[1]) # 16
############################################################
# write with reinterpret -- this does work
############################################################
function write_reinterpret(io, x)
@assert isbits(typeof(x))
write(io, reinterpret(UInt8, [x]))
end
io = open(path, "w")
for elt in x
write_reinterpret(io, elt)
end
close(io)
## read
io = open(path, "r")
y = Mmap.mmap(io, Vector{Record{T1, T2}}, (length(x),))
x == y # true
############################################################
# write with reinterpret -- this DOES WORK
############################################################
function write_struct_unsafe(io, x::T) where {T}
@assert isbits(T)
unsafe_write(io, Ref(x), sizeof(x)) # am I using this the right way?
end
io = open(path, "w")
for elt in x
write_struct_unsafe(io, elt)
end
close(io)
## read
io = open(path, "r")
y = Mmap.mmap(io, Vector{Record{T1, T2}}, (length(x),))
x == y # true
Related discussion:
https://github.com/JuliaLang/julia/issues/10140
https://github.com/JuliaLang/julia/issues/10354