# Reading and writing BigInt to file

**URL:** https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726
**Category:** General Usage
**Created:** [March 9, 2025, 6:47am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726 "2025-03-09T06:47:44Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 9, 2025, 6:47am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/1 "2025-03-09T06:47:44Z")

</div>

I’m writing a package that creates a cryptographic key consisting of big prime numbers, and I need to write them to a file and read them back. Is there a preexisting library that does this, or do I have to write the code myself? Is a four-byte length big enough for `BigInt` in general?

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [March 9, 2025, 8:05am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/2 "2025-03-09T08:05:25Z")

</div>

You could write the prime numbers, one per line, to an ordinary text file with `println`, then read them back with `readlines` and parse back to BigInt with `parse(BigInt, line)`.

No. Not all `BigInt`s fit in four bytes. They can be arbitrarily big.

---

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 9, 2025, 8:09am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/3 "2025-03-09T08:09:26Z")

</div>

A `BigInt` can have more than 4294967295 bytes? I seriously doubt I’ll need a prime number that big, but if `BigInt`s can be bigger than that, then the library should use an eight-byte length.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [March 9, 2025, 8:10am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/4 "2025-03-09T08:10:44Z")

</div>

To elaborate, there might be something out there more specific to GMP (which `BigInt` is built on), but writing out the integer in text can apply to any format. Here’s an example:

```julia
open("twotohundred.txt","w") do f
    print(f, BigInt(2)^100)
end

```

That converts the `BigInt` to a `String` with the function `string` in a deeper call, so it’ll look as you’d expect. If you use `string` directly, you can also use `write` instead of `print`. You can delimit the integers with more than newlines, you can `print` or `write` anything.

GMP’s integer data increments at word size, that’s 4 bytes for 32-bit systems and 8 bytes for 64-bit systems. Converted to UTF-8 text in base 10 though, that’s 1 byte per digit.

> [@phma](#):
>
> A `BigInt` can have more than 4294967295 bytes?

Sure, if you have enough working memory for it.

---

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 9, 2025, 8:16am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/5 "2025-03-09T08:16:24Z")

</div>

No delimiter is necessary, because the number of bytes in the `BigInt` will be written before the bytes themselves.

The number will be written as bytes, 8 bits per byte, not as decimal digits, 3.3 bits per byte.

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [March 9, 2025, 8:22am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/6 "2025-03-09T08:22:26Z")

</div>

> [@phma](#):
>
> A `BigInt` can have more than 4294967295 bytes?

I’ve never actually tried this, but the GMP library webpage [https://gmplib.org](https://gmplib.org) states that the precision is only limited by available memory, so on a 64 bit system that could be more than 4 GB.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [March 9, 2025, 8:33am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/7 "2025-03-09T08:33:01Z")

</div>

> [@phma](#):
>
> the number of bytes in the `BigInt` will be written before the bytes themselves. The number will be written as bytes, 8 bits per byte

Definitely possible, GMP has functions for [raw IO](https://gmplib.org/manual/I_002fO-of-Integers) like this, and even if it didn’t, we have access to the raw data via `BigInt`, just a matter of figuring out how much to read from the pointer. But I don’t know `BigInt` or `ccall` well enough to do this.

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [March 9, 2025, 8:40am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/8 "2025-03-09T08:40:49Z")

</div>

> [@phma](#):
>
> The number will be written as bytes, 8 bits per byte, not as decimal digits, 3.3 bits per byte.

Is this really worth the extra effort? For a 4096-bit cryptographic key, this is less than a kilobyte of disk space saved…

---

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 9, 2025, 8:42am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/9 "2025-03-09T08:42:27Z")

</div>

It says it writes four bytes of size. However:

```julia
julia> big(256)^444;

julia> big(256)^2147483647;

julia> big(256)^2147483648;

julia> big(256)^4294967295;

julia> big(256)^4294967296;

julia> big(256)^5294967296;

julia> big(256)^5294967296%7
Killed

```

Julia can hold a number bigger than that, but on this computer can’t compute with it.

---

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 9, 2025, 8:46am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/10 "2025-03-09T08:46:02Z")

</div>

It’s more effort to convert it to decimal than to write the bytes as they are. Not that it matters much, as writing is I/O-bound. But most of the key files I’ve seen are either binary or base64 encoded, not decimal.

---

<div class="post-metadata">

### Author: ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)
#### Post date: [March 9, 2025, 9:02am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/11 "2025-03-09T09:02:19Z")

</div>

> [@phma](#):
>
> Julia can hold a number bigger than that, but on this computer can’t compute with it.

In that case, your computer is not going to find a prime number that needs more than [17 megabytes](https://en.wikipedia.org/wiki/Largest_known_prime_number) of storage either… 😉

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [March 9, 2025, 9:27am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/12 "2025-03-09T09:27:39Z")

</div>

My god, 1 year, thousands of GPUs, and $2M just to find a 17MB-ish `BigInt` we can instantiate in a few ms. I guess the eternal bragging rights is worth more than crypto or AI bot profits.

---

<div class="post-metadata">

### Author: ![Janis\_Erdmanis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janis_erdmanis/32/10869_2.png) [@Janis\_Erdmanis](https://discourse.julialang.org/u/Janis_Erdmanis)
#### Post date: [March 9, 2025, 9:43am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/13 "2025-03-09T09:43:28Z")

</div>

If you are not bothered by serialisation performance, you could use `parse(BigInt, bytes2hex(x), base=16)` and the reverse `hex2bytes(string(x; base=16))`. This, however, adds unnecessary computation and memory overhead, and you may benefit from `int2octet` and `octet2int` methods as implemented in CryptoGroups.jl as [shown in the following line](https://github.com/PeaceFounder/CryptoGroups.jl/blob/0f6b4e223225634ec1506e6999f8922c079f62c7/src/Utils.jl#L148).

---

<div class="post-metadata">

### Author: ![caleb-allen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/caleb-allen/32/14054_2.png) [@caleb-allen](https://discourse.julialang.org/u/caleb-allen)
#### Post date: [March 9, 2025, 4:20pm UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/14 "2025-03-09T16:20:46Z")

</div>

iirc GMP BigInt performance for parsing from a string is quite bad (in my experience with integers of a couple MB).

That said, I believe there is a GMP method for serializing and deserializing based on their in-memory representation. The problem is that it is not exposed on the Julia side.

I think I played around with calling the C function directly, I could go back and find it if there’s interest (I think it’d be worth submitting a PR to Julia, too)

---

<div class="post-metadata">

### Author: ![Janis\_Erdmanis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/janis_erdmanis/32/10869_2.png) [@Janis\_Erdmanis](https://discourse.julialang.org/u/Janis_Erdmanis)
#### Post date: [March 9, 2025, 4:46pm UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/15 "2025-03-09T16:46:53Z")

</div>

For serialising `BigInt` to the buffer there is:

```julia
_, written = GMP.MPZ.export!(@view(buffer[end-needed_bytes+1:end]), n;
                                 order = 1, # Big-endian
                                 endian = 0, # Native endian
                                 nails = 0 # Use all bits
                                 )

```

However there does not seem to be an inverse method. At least I haven’t managed to find one.

---

<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: [March 9, 2025, 6:29pm UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/16 "2025-03-09T18:29:41Z")

</div>

> [@Janis\_Erdmanis](#):
>
> However there does not seem to be an inverse method. At least I haven’t managed to find one.

Yes, we need a wrapper of [`mpz_import`](https://gmplib.org/manual/Integer-Import-and-Export). Shouldn’t be hard to write. Could maybe improve the performance of the `serialize` and `deserialize` functions too?

Serialization currently uses [`str = string(n, base=62)`](https://github.com/JuliaLang/julia/blob/7d84c5369b869eec22a9478e0ea492488e880e6d/stdlib/Serialization/src/Serialization.jl#L346-L349) and `parse(BigInt, str, base = 62)` to convert more efficiently to/from a buffer without going through decimal, so that’s also an option. (62 is the biggest base that you can represent with 1-byte `[0-9A-Za-z]` digits.

---

<div class="post-metadata">

### Author: ![phma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phma/32/6576_2.png) [@phma](https://discourse.julialang.org/u/phma)
#### Post date: [March 10, 2025, 6:47pm UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/17 "2025-03-10T18:47:15Z")

</div>

Okay, it looks like I’ll write my own code to do this.

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [March 11, 2025, 1:54am UTC](https://discourse.julialang.org/t/reading-and-writing-bigint-to-file/126726/18 "2025-03-11T01:54:58Z")

</div>

Unless there is a need for compact binary representation, text-editor compatible output, as stevengj suggested is best.  
Even using `base = 60` just as a nod to Babylonian times and to keep a couple of sentinal values for `begin`, `end` and other special digits (possible even prep for BigFloat serialization).
