# Write struct into binary file and read it back

**URL:** https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648
**Category:** New to Julia
**Tags:** question
**Created:** [July 11, 2025, 5:43pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648 "2025-07-11T17:43:19Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![Krisztian\_Novak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krisztian_novak/32/216598_2.png) [@Krisztian\_Novak](https://discourse.julialang.org/u/Krisztian_Novak)
#### Post date: [July 11, 2025, 5:43pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/1 "2025-07-11T17:43:19Z")

</div>

I try to write a struct into a binary file and read it back.  
My code is the following:

```julia
struct STRUCT
    x::Float64
    y::Float64
    z::Float64
end

isbitstype(STRUCT)

rp = STRUCT(2.0, 3.0, 4.0)

open("test.bin", "w") do io
    write(io, rp)
end

open("test.bin", "r") do io
    rp2 = read(io, STRUCT)
    @show rp2
end

```

I got the following error:

```julia
ERROR: MethodError: no method matching write(::IOStream, ::STRUCT)
This error has been manually thrown, explicitly, so the method may exist but be intentionally marked as unimplemented.

Closest candidates are:
  write(::IO, ::Any)
   @ Base io.jl:792
  write(::IO, ::Any, Any...)
   @ Base io.jl:793
  write(::IO, ::Union{Base.AnnotatedString, SubString{<:Base.AnnotatedString}})
   @ StyledStrings C:\Users\kiki\.julia\juliaup\julia-1.11.5+0.x64.w64.mingw32\share\julia\stdlib\v1.11\StyledStrings\src\io.jl:258
  ...

Stacktrace:
 [1] write(io::IOStream, x::STRUCT)
   @ Base .\io.jl:792
 [2] (::var"#15#16")(io::IOStream)
   @ Main w:\a\2d distribution\struct RAYPATH.jl:13
 [3] open(::var"#15#16", ::String, ::Vararg{String}; kwargs::@Kwargs{})
   @ Base .\io.jl:410
 [4] open(::Function, ::String, ::String)
   @ Base .\io.jl:407
 [5] top-level scope
   @ w:\a\2d distribution\struct RAYPATH.jl:12

```

What is the problem?  
`isbitstype(STRUCT)` returns true.

---

<div class="post-metadata">

### Author: ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)
#### Post date: [July 11, 2025, 6:26pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/2 "2025-07-11T18:26:33Z")

</div>

You want to write an instance of type `STRUCT` to a file, but you have to implement the `write` method in order to do that, otherwise Julia cannot simply assume how a generic type should be saved.  
The fact that `isbitstype` returns `true` means something different, not sure why you would expect that to be linked

---

<div class="post-metadata">

### Author: ![Pedro](https://avatars.discourse-cdn.com/v4/letter/p/919ad9/32.png) [@Pedro](https://discourse.julialang.org/u/Pedro)
#### Post date: [July 11, 2025, 6:44pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/3 "2025-07-11T18:44:23Z")

</div>

Well, you can use `reinterpret`.

```julia
struct STRUCT
    x::Float64
    y::Float64
    z::Float64
end

isbitstype(STRUCT)

rp = STRUCT(2.0, 3.0, 4.0)

open("test.bin", "w") do io
    write(io, reinterpret(Int8, [rp,]))
end

open("test.bin", "r") do io
    rp2 = reinterpret(STRUCT, read(io))
    @show rp2
end

```

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [July 11, 2025, 6:46pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/4 "2025-07-11T18:46:38Z")

</div>

> [@Pedro](#):
>
> `rp2 = reinterpret(STRUCT, read(io))`

Or perhaps `rp2 = only(reinterpret(STRUCT, read(io)))` if you want to get a `STRUCT` out (i.e. `rp` instead of `[rp]`).

Edit:

> [@VinceNeede](#):
>
> The fact that `isbitstype` returns `true` means something different, not sure why you would expect that to be linked

Pedro’s approach would naturally work for any `isbitstype`, so there could have been a default implementation for `write` in this case.

---

<div class="post-metadata">

### Author: ![jbytecode](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbytecode/32/17719_2.png) [@jbytecode](https://discourse.julialang.org/u/jbytecode)
#### Post date: [July 11, 2025, 6:51pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/5 "2025-07-11T18:51:16Z")

</div>

I am not sure if you are trying this for educational purposes, but there are many ways to serialize objects, for example JSON format is an option.

Julia has the Serialization package in its standard library. How about doing this:

```julia
julia> using Serialization

julia> struct STRUCT
           x::Float64
           y::Float64
           z::Float64
       end

julia> s = STRUCT(1.0, 2.0, 3.0)
STRUCT(1.0, 2.0, 3.0)

julia> serialize("output.dat", s)

```

and then

```julia
julia> object = deserialize("output.dat")
STRUCT(1.0, 2.0, 3.0)

```

---

<div class="post-metadata">

### Author: ![brianguenter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brianguenter/32/29519_2.png) [@brianguenter](https://discourse.julialang.org/u/brianguenter)
#### Post date: [July 11, 2025, 7:00pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/6 "2025-07-11T19:00:22Z")

</div>

If you use the Serialization package be aware that the file format may not be compatible across different machines or OS’es. From the docs:

> In some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code."

---

<div class="post-metadata">

### Author: ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)
#### Post date: [July 11, 2025, 7:03pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/7 "2025-07-11T19:03:55Z")

</div>

This can be an example, you can see that the file has a size of 24Bytes

```julia-repl
julia> struct MyStruct
           x::Float64
           y::Float64
           z::Float64
       end

julia> function Base.write(io::IOStream, ms::MyStruct)
           write(io, ms.x)
           write(io, ms.y)
           write(io, ms.z)
       end

julia> function Base.read(io::IOStream, ::Type{MyStruct})
           x = read(io, Float64)
           y = read(io, Float64)
           z = read(io, Float64)
           return MyStruct(x, y, z)
       end
julia> open("test.bin", "w") do io
           write(io, MyStruct(2.0, 3.0, 4.0))
       end
8

shell> stat test.bin
  File: test.bin
  Size: 24    

julia> open("test.bin", "r") do io
           read(io, MyStruct)
       end
MyStruct(2.0, 3.0, 4.0)

```

> [@eldee](#):
>
> Pedro’s approach would naturally work for any `isbitstype`, so there could have been a default implementation for `write` in this case

Not sure I’d like that

> [@jbytecode](#):
>
> Serialization package

It seems to give an overhead, don’t know why

```julia-repl

julia> serialize("output.dat", MyStruct(1.0, 2.0, 3.0))

shell> stat output.dat
  File: output.dat
  Size: 56 

```

---

<div class="post-metadata">

### Author: ![jbytecode](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbytecode/32/17719_2.png) [@jbytecode](https://discourse.julialang.org/u/jbytecode)
#### Post date: [July 11, 2025, 7:06pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/8 "2025-07-11T19:06:02Z")

</div>

Just because the serialized file carries a set of header information:

> **[Serialization · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Serialization/#Serialization.writeheader)**
>
> Documentation for The Julia Language.

---

<div class="post-metadata">

### Author: ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)
#### Post date: [July 11, 2025, 7:09pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/9 "2025-07-11T19:09:00Z")

</div>

The header should be 8 bytes, but the overhead is 32 Bytes

---

<div class="post-metadata">

### Author: ![jbytecode](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbytecode/32/17719_2.png) [@jbytecode](https://discourse.julialang.org/u/jbytecode)
#### Post date: [July 11, 2025, 7:11pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/10 "2025-07-11T19:11:13Z")

</div>

It is not documented in a great detail but the file also includes the module name (in my case it’s Main) and the name of the structure.

Edit: I think the module name and the struct name have also headers (because of strings).

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [July 11, 2025, 7:18pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/11 "2025-07-11T19:18:05Z")

</div>

I would use [GitHub - JuliaIO/StructIO.jl: binary I/O methods generated from Julia structure definitions](https://github.com/JuliaIO/StructIO.jl) if you want to write the “raw bits” of the structure to disk (as opposed to some higher-level package like JLD.jl or Serialization). For example, this gives you control of field padding.

---

<div class="post-metadata">

### Author: ![Krisztian\_Novak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krisztian_novak/32/216598_2.png) [@Krisztian\_Novak](https://discourse.julialang.org/u/Krisztian_Novak)
#### Post date: [July 11, 2025, 7:53pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/12 "2025-07-11T19:53:22Z")

</div>

My goal is to read a binary file generated by Zemax (optical simulation software). But because that did not worked, I tried to make a minimal example.  
Having C/C++ background, it is strange, that it is so complicated to write/read N structs.

But with reinterpret or by overloading read/write I was able to overcome the problem.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [July 11, 2025, 8:13pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/13 "2025-07-11T20:13:14Z")

</div>

> [@Krisztian\_Novak](#):
>
> My goal is to read a binary file generated by Zemax (optical simulation software).

That’s exactly the use case for StructIO.jl

> [@Krisztian\_Novak](#):
>
> Having C/C++ background, it is strange, that it is so complicated to write/read N structs.

You need to specify the struct alignment/padding for an on-disk format, if you don’t want it to be compiler/ABI-dependent. That’s what StructIO.jl does.

(And then there is the question of endian conversion, though most things are little-endian these days. But Julia has functions like `ntoh` to do endian conversion.)

---

<div class="post-metadata">

### Author: ![xgdgsc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xgdgsc/32/608_2.png) [@xgdgsc](https://discourse.julialang.org/u/xgdgsc)
#### Post date: [July 12, 2025, 1:32am UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/14 "2025-07-12T01:32:50Z")

</div>

You may want to use CBinding.jl if you already have the c struct headers.

---

<div class="post-metadata">

### Author: ![arbitrandomuser](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/arbitrandomuser/32/19374_2.png) [@arbitrandomuser](https://discourse.julialang.org/u/arbitrandomuser)
#### Post date: [July 17, 2025, 10:12am UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/15 "2025-07-17T10:12:22Z")

</div>

> [@brianguenter](#):
>
> If you use the Serialization package be aware that the file format may not be compatible across different machines or OS’es. From the docs:
> 
> > In some cases, the word size (32- or 64-bit) of the reading and writing machines must match. In rarer cases the OS or architecture must also match, for example when using packages that contain platform-dependent code."

Also might fail across package versions.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [July 17, 2025, 3:25pm UTC](https://discourse.julialang.org/t/write-struct-into-binary-file-and-read-it-back/130648/16 "2025-07-17T15:25:42Z")

</div>

> [@arbitrandomuser](#):
>
> Also might fail across package versions.

Nothing really could save you from that.  
Updating package version can lead to new fields added/old fields removed/struct renamed/… .
