I am trying to save my designed structure into a file. However, when I am trying to read it, its structure seems to be lost. Any idea how to maintain its structure and do it correctly?
using FileIO, JLD
mutable struct S
id::Vector{String}
value::Vector{Float64}
end
CP=S[];
push!(CP, S(["3d4f7006", "3d4f7006"], [2.0,3.0]));
push!(CP, S(["3d5ce1ef", "3d5ce1ef"], [7.0,8.0]));
save("SavedObjects.jld", "CP",CP)
save("SavedObjects.jld", "CP",CP])
#####
d = load("SavedObjects.jld")
┌ Warning: type S not present in workspace; interpreting array as Array{Any}
└ @ JLD C:\Users\amroa\.julia\packages\JLD\JHrZe\src\JLD.jl:514
┌ Warning: type S not present in workspace; reconstructing
└ @ JLD C:\Users\amroa\.julia\packages\JLD\JHrZe\src\jld_types.jl:697
Dict{String, Any} with 1 entry:
"CP" => Any[var"##S#257"(["3d4f7006", "3d4f7006"], [2.0, 3.0]), var"##S#257"(["3d5ce1ef", "3d5ce1ef"], [7.0, 8.0])]
julia> d[2].id[1] # here I expect to return "3d5ce1ef"
ERROR: KeyError: key 2 not found
Stacktrace:
[1] getindex(h::Dict{String, Any}, key::Int64)
@ Base .\dict.jl:482
[2] top-level scope
@ REPL[3]:1
I have tried various packages for this purpose. In the end, JLD2 works best for me. It works most of the time. But sometimes a set of files ends up unreadable later on (I don’t know why).
My rule is therefore: I use JLD2 for convenience. But when I cannot lose something, I write it to a text file using JSON3.
One point to note: when the file is read, the struct to be reconstructed needs to be accessible in Main; otherwise a reconstructed object is constructed instead (which has the same fields as the original one). (The last point is from the JLD2 documentation from some time ago; please correct me if this is no longer true).
using FileIO, JLD2
mutable struct S
id::Vector{String}
value::Vector{Float64}
end
CP=S[];
push!(CP, S(["3d4f7006", "3d4f7006"], [2.0,3.0]));
push!(CP, S(["3d5ce1ef", "3d5ce1ef"], [7.0,8.0]));
save("My_file.jld2", "CP",CP)
ERROR: LoadError: too many parameters for type
Stacktrace:
using StructTypes
using JSON3
StructTypes.StructType(::Type{SolSummary}) = StructTypes.Struct()
StructTypes.StructType(::Type{MutableResult}) = StructTypes.Struct()
StructTypes.StructType(::Type{Result}) = StructTypes.Struct()
StructTypes.StructType(::Type{Density}) = StructTypes.Struct()
StructTypes.StructType(::Type{Volume}) = StructTypes.Struct()
StructTypes.StructType(::Type{Options}) = StructTypes.Struct()
function save(R::Result, filename::String)
f = open(filename,"w")
JSON3.write(f,R)
close(f)
end
My function to load the struct has a complication, because you cannot save multidimensional arrays in JSON3:
unction load(filename::String)
f = open(filename,"r")
R = JSON3.read(f,MutableResult)
# Need to reshape the solute and solvent atom contributions, because
# the data is read in a single column
solute_atom = reshape(R.solute_atom,R.nbins,:)
solvent_atom = reshape(R.solvent_atom,R.nbins,:)
R.solute_atom = solute_atom
R.solvent_atom = solvent_atom
return Result([getfield(R,field) for field in fieldnames(Result)]...)
end
I cannot say much more, I only followed instructions until that worked out.
No, SolSummaryand the other names are the names of the structs I have in my code.
Ah, but I noticed now that you want to save a vector of structs, each of which has vectors as fields… I think that won’t work using JSON3 without a bit of tinkering.