# Open, read and write binary into a file

**URL:** https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126
**Category:** Help & Support
**Created:** [December 7, 2021, 6:03pm UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126 "2021-12-07T18:03:16Z")
**Posts on this page:** 5
**Page:** 2

<div class="post-metadata">

### Author: ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)
#### Post date: [December 14, 2021, 9:34pm UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126/22 "2021-12-14T21:34:31Z")

</div>

I think it’s completely clear ! A pleasure to see you by camera, definitely better !

---

<div class="post-metadata">

### Author: ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)
#### Post date: [December 17, 2021, 2:07am UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126/23 "2021-12-17T02:07:40Z")

</div>

I have an another question now. If I would like to do the opposite ? If I would like to export a class to a json file, how I can do that ? With wich method ? to\_json method ?

For example, this is one of my implementation with json. I’m already able to import json data file.  
How can I export a SoftwareInformation data to json file ?

```auto
module ISM

  class SoftwareInformation

    record Option,
        name : String,
        description : String,
        active : Bool do
        include JSON::Serializable
    end
    
    record Dependency,
        name : String,
        version : String,
        options : Array(Option) do
        include JSON::Serializable
    end
    
    record Information,
        name : String,
        version : String,
        architectures : Array(String),
        description : String,
        website : String,
        downloadLinks : Array(String),
        signatureLinks : Array(String),
        shasumLinks : Array(String),
        dependencies : Array(Dependency),
        options : Array(Option) do
        include JSON::Serializable
    end

    property name = ISM::Default::SoftwareInformation::Name
    property version = ISM::Default::SoftwareInformation::Version
    property architectures = ISM::Default::SoftwareInformation::Architectures
    property description = ISM::Default::SoftwareInformation::Description
    property website = ISM::Default::SoftwareInformation::Website
    property downloadLinks = ISM::Default::SoftwareInformation::DownloadLinks
    property signatureLinks = ISM::Default::SoftwareInformation::SignatureLinks
    property shasumLinks = ISM::Default::SoftwareInformation::ShasumLinks
    property dependencies = ISM::Default::SoftwareInformation::Dependencies
    property options = ISM::Default::SoftwareInformation::Options

    def initialize( name = ISM::Default::SoftwareInformation::Name,
                    version = ISM::Default::SoftwareInformation::Version,
                    architectures = ISM::Default::SoftwareInformation::Architectures,
                    description = ISM::Default::SoftwareInformation::Description,
                    website = ISM::Default::SoftwareInformation::Website,
                    downloadLinks = ISM::Default::SoftwareInformation::DownloadLinks,
                    signatureLinks = ISM::Default::SoftwareInformation::SignatureLinks,
                    shasumLinks = ISM::Default::SoftwareInformation::ShasumLinks,
                    dependencies = ISM::Default::SoftwareInformation::Dependencies,
                    options = ISM::Default::SoftwareInformation::Options)

                    @name = name
                    @version = version
                    @architectures = architectures
                    @description = description
                    @website = website
                    @downloadLinks = downloadLinks
                    @signatureLinks = signatureLinks
                    @shasumLinks = shasumLinks
                    @dependencies = dependencies
                    @options = options
    end

    def loadInformationFile(informationFilePath = ISM::Default::Software::InformationFilePath)
      information = Information.from_json(File.read(informationFilePath))

      @name = information.name
      @version = information.version
      @architectures = information.architectures
      @description = information.description
      @website = information.website
      @downloadLinks = information.downloadLinks
      @signatureLinks = information.signatureLinks
      @shasumLinks = information.shasumLinks

      information.dependencies.each do |data|
          dependency = ISM::SoftwareDependency.new
          dependency.name = data.name
          dependency.version = data.version
          data.options.each do |entry|
              option = ISM::SoftwareOption.new
              option.name = entry.name
              option.description = entry.description
              option.active = entry.active
              dependency.options.push(option)
          end
          @dependencies.push(dependency)
      end
      
      information.options.each do |data|
          option = ISM::SoftwareOption.new
          option.name = data.name
          option.description = data.description
          @options.push(option)
      end
    
    end

    def versionName
        return @name+"-"+@version
    end

  end

end

```

---

<div class="post-metadata">

### Author: ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)
#### Post date: [December 17, 2021, 2:45pm UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126/24 "2021-12-17T14:45:35Z")

</div>

I think I found a part of the solution:  
(it’s an example)

```auto
record Information,
        name : String,
        version : String,
        architectures : Array(String) do
        include JSON::Serializable
end

sft = Information.new("Binutils","2.37",["x86_64","arm"])
puts sft.name

sft.to_json(File.open("Test.json","w"))

```

But can I provide a default value of my record properties ? Because I would like for example to setup an empty record, and after for example do :

```auto

sft = Information.new
sft.name = "Something"

```

---

<div class="post-metadata">

### Author: ![RespiteSage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/respitesage/32/793_2.png) [@RespiteSage](https://forum.crystal-lang.org/u/RespiteSage)
#### Post date: [December 17, 2021, 4:39pm UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126/25 "2021-12-17T16:39:59Z")

</div>

The default value is easy:

```crystal
record Information,
        name : String = "DefaultName",
        version : String = "0.0.1",
        architectures : Array(String) = ["x86_64"] do
        include JSON::Serializable
end

```

However, modifying it is more complicated. The `record` macro is designed for creating immutable Structs (i.e. you can’t change them after they’re created). You could instead just use a standard `Struct` definition:

```crystal
require "json"

struct Information
  include JSON::Serializable
  property name : String = "DefaultName"
  property version : String = "0.0.1"
  property architectures : Array(String) = ["x86_64"]
  
  def initialize
  end
  
  def initialize(@name, @version, @architectures)
  end
end

sft = Information.new("Binutils","2.37",["x86_64","arm"])
puts sft.name # => Binutils

puts sft.to_json # => {"name":"Binutils","version":"2.37","architectures":["x86_64","arm"]}

default = Information.new
puts default.to_json # => {"name":"DefaultName","version":"0.0.1","architectures":["x86_64"]}

non_default = default.dup
non_default.name = "NonDefault"

puts non_default.to_json # => {"name":"NonDefault","version":"0.0.1","architectures":["x86_64"]}

```

[Run it](https://carc.in/#/r/cgko)

As always when using Structs, you need to remember that they’re passed by value: [docs](https://crystal-lang.org/api/1.2.2/Struct.html).

---

<div class="post-metadata">

### Author: ![jgaskins](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jgaskins/32/2449_2.png) [@jgaskins](https://forum.crystal-lang.org/u/jgaskins)
#### Post date: [December 22, 2021, 2:44am UTC](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126/26 "2021-12-22T02:44:10Z")

</div>

> [@RespiteSage](#):
>
> As always when using Structs, you need to remember that they’re passed by value

This is precisely the reason the `record` macro makes objects immutable. :-D If your objects accumulate their own state outside of `initialize`, it’s almost always a good idea to use `class` instead. It’s too easy to get confused when changed state of a struct doesn’t stick.

[Previous page](https://forum.crystal-lang.org/t/open-read-and-write-binary-into-a-file/4126.md?page=1)
