Saving/Loading Files - Is there any build-in file parsing I can use? How?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Tybobobo
:warning: Old Version Published before Godot 3 was released.

I am trying to create and read .cfg files, that have the following format:

hostname=“My server”
maxclients=32


Is there any in-build support for reading .cfg files (or other files)?
What about .json formatting?

My goal is to have easily configurable files for the user; and to easily be able to load data from it. :slight_smile:

:bust_in_silhouette: Reply From: Bojidar Marinov

You should have a look into ConfigFile APIs. They have a bit different format though, more like .desktop files:

[section_name]
name=value

To read .json files, you might use the File class to read the file, and then use Dictionary::parse_json on the contents.

Thanks a lot :slight_smile:
The ConfigFile works great for this - I wont have to use Json until later :slight_smile:

Tybobobo | 2016-02-25 16:46

:bust_in_silhouette: Reply From: brunosxs

Yep, there is a ConfigFile class that can help you with this.

var file_to_save= "user://configuration.ini"
    func _ready():
     var configFile= ConfigFile.new() # creates and initializes a ConfigFile
     configFile.set_value("Config","hostname","myworkgroup") #Sets the value myworkgroup to Config > hostname
     configFile.set_value("Config","maxClients",32)
     configFile.save(file_to_save)

This would create a file with the syntax:

[Config]

hostname = “my workgroup”
maxClients = 32

Search on the built-in documentation for the ConfigFile class

I am unable to find the file after running this. However, if I change it to res:// I can see it in the project folder. :<

Tybobobo | 2016-02-25 16:24

Works perfect when I use res:// instead of user:// :slight_smile:

Tybobobo | 2016-02-25 16:47

You can use print(OS.get_data_dir()) to see the location of user:// :slight_smile:

Hinsbart | 2016-02-25 16:53

Generally, you should always use user:// instead of res:// since res:// is not writable in the following cases:

  • Running on Android/iOS
  • Running when installed system-wide (eg. on C:\Program Files on Windows)

On Windows, user:// is found in %APPDATA\Godot\app_userdata\Game Name, on GNU/Linux it’s in ~/.godot/app_userdata/Game Name.


Also note that ConfigFile is a bit limited right now. It can store booleans, strings, integers and floats, but can’t store arrays or dictionaires, unless you split them (using spaces or commas for example) in the case of arrays or convert them to JSON in the case of dictionaries. You also can’t have comments in the ConfigFile you’re using.

Improvements to ConfigFile may happen in 3.0.

Calinou | 2016-02-25 16:59

Yeah, this is the reason that I personally never used it in my project.
But for what he wants, the config file will be perfect…

brunosxs | 2016-02-25 17:23

I will probably end up writing my own load/save file code in order to manage it properly. For now though, I will keep using ConfigFile until that time comes.

Tybobobo | 2016-02-26 14:24

Hi HInsbard,

  • I am trying to use the File class to save and load data, when it runs on Desktop (Editor), it works fine.
    But when it runs on Android, it couldn’t find the file. (Note: tried both “user” and “res”, nothing’s fixed)

raidenbigboss | 2016-02-26 15:48

Yeah File/Directory seem to be pretty broken on Android (and a bit on Windows). You can’t see a dir contents or delete a file. File.open() always returns False even when it succeeds. Directory.file_ exists() doesn’t seem to work (but File.file_ exists() does)…

duke_meister | 2016-03-27 22:23

:bust_in_silhouette: Reply From: Tybobobo

Thank you all for the help! From the answers posted here I managed to create a saving and loading script using ConfigFiles. I usually create my own tutorials in a private site, but I am going to share what I wrote here - so that others may have use of it :slight_smile:


Documentation:


Saving a File

# Path to save file 
var file_to_save= "res://configuration.cfg" 
 
func _ready(): 
	# Initiate ConfigFile 
	var configFile = ConfigFile.new()  
 
	# Add values to file 
	configFile.set_value("Config","hostname","Server name") 
	configFile.set_value("Config","maxClients",32) 
	configFile.set_value("Options","difficulty","hard") 
 
	# Save file 
	configFile.save(file_to_save)

Saved Output

[Config] 

hostname=“Server name”
maxClients=32

[Options]

difficulty=“hard”


Loading a File

var file_to_load= "res://configuration.cfg" 

func _ready():
# Initiate ConfigFile
var configFile= ConfigFile.new()

# Load file 
configFile.load(file_to_load) 

# ---------- 

# METHOD-1: 
# Check if "hostname" exists in Config section 
if (configFile.has_section_key("Config", "hostname")): 

	# Get hostname value and print it 
	var hostName = configFile.get_value("Config", "hostname") 
	print("Hostname: ", hostName) 

# ---------- 

# METHOD-2: 
# Assign value without checking if it exists 
var maxClients = configFile.get_value("Config", "maxclients") 

# If value is not null; print out 
if(maxClients != null): 
	print("Max Clients: ", maxClients) 

# ---------- 

# Check if [Options] section exist 
if (configFile.has_section("Options")): 
	print ("Options found!") 

Output

Hostname: Server name 
Max Clients: 32 
Options found! 

Personal Notes
It was recommended that I use user:// in path… which apparently is supposed to save the file in my ~/godot directory. I was unable to find any file there, and I am wondering it is because I am using Windows 7.

However I believe using res:// is a better option, as I would want the config file to be in the root directory of the game I am working on, so that people may easily change values if needed (such as server configurations). Tips & Tricks are welcome! :slight_smile:

The file will be packed with all the resources to the .exe/linux file when you compile your project, so there will be no way to edit it afterwards if you use “res://”
edit: Tried this with early builds of godot, don’t know if this behavior changed.

brunosxs | 2016-02-26 14:36