Godot Version
Godot 4.4.Stable
Question
Ask your question here! Try to give as many details as possible
Hello, First post on the forum.
I have spent a while making a game, and have just gotten to testing it as an exe.
After each level, the result is updated to a dictionary and all results are written to a text file.
The function performing the writing is:
##Overwrite the file at the designated location with the provided dictionary.
##First makes a file if none exists. (Current implementation will not make more than one directory at a time)
func SetDictionaryAsFile(directorypath : String, filename : String, fileContents : Dictionary):
var fullpath = directorypath + filename
var string = JSON.stringify(fileContents,"\t")
#Create file
DirAccess.make_dir_absolute(directorypath)
var file = FileAccess.open(fullpath,FileAccess.READ)
if file == null:
push_error("@FileManager.SetDictionaryAsFile. File (", fullpath ,") failed to be created and/or open.")
push_error("Error: ", FileAccess.get_open_error())
else:
file.close()
#Write to file
file = FileAccess.open(fullpath, FileAccess.WRITE)
if file == null:
push_error("@FileManager.SetDictionaryAsFile. File (", fullpath ,") failed to be opened for write.")
push_error("Error: ", FileAccess.get_open_error())
file.store_string(string)
file.close()
file = null
The push errors handling the FileAccess.WRITE prints out (to the console) as:
ERROR: @FileManager.SetDictionaryAsFile. File (res://Profiles/DemoProfile/Profile1.txt) failed to be opened for write.
at: push_error (core/variant/variant_utility.cpp:1098)
ERROR: Error: 7
at: push_error (core/variant/variant_utility.cpp:1098)
Error 7 being ERR_FILE_NOT_FOUND according to GlobalscopeErrors
The push_errors regarding the FileAccess.READ do not print (so I assume that the file is successfully created or otherwise found.)
This code works fine for Debug testing (testing with f5) (Well the FileAccess.READ does push errors in that case, but the file still gets made, and the correct data added, so it functionally succeeds.)
Thank you!
You should be able to see the file on the disk from the command line or in a file browser (that is, outside your game). Is it there? Are the permissions on it sane? Is the name capitalized the way you think it should be?
For the filepath and name consistency I use constants:
#User Save States
const ProfilesDirectory : String = "res://Profiles/DemoProfile/"
const ProfileFilename : String = "Profile1.txt"
And those constants are the first two arguments in the function, respectively.
When working in the Godot editor the file does appear in the FileSystem, and can be accessed by file browser. (I am on windows)
When attempting to generate it from the executable version… I’m not sure. I assumed that it would be relative to res://, and therefore appear in the exe itself? But I suppose that is a bit odd, and possibly a bad assumption.
I guess that begs the question, does saving data to a file require certain settings after the game is exported?
I just tested the exported version with the file already there. It reads the data fine, but still does not write to it.
Ah, I think that’s your problem. If you’re going to write files, I think they need to go in user://
, not in res://
.
edit: typo.
Thank you, this now seems to work (but thats for my playtesters to confirm
)
For any who comes afterwards, the code now looks like:
##Overwrite the file at the designated location with the provided dictionary.
##First makes a file if none exists.
func SetDictionaryAsFile(directorypath : String, filename : String, fileContents : Dictionary):
var fullpath = directorypath + filename
var string = JSON.stringify(fileContents,"\t")
#Create Directory if non-existant
if not DirAccess.dir_exists_absolute(directorypath):
DirAccess.make_dir_recursive_absolute(directorypath)
#Create file
var file = FileAccess.open(fullpath,FileAccess.READ)
if file == null: #Errors on first file creation.
push_error("@FileManager.SetDictionaryAsFile. File (", fullpath ,") failed to be created and/or open.")
push_error("Error: ", FileAccess.get_open_error())
else:
file.close()
#Write to file
file = FileAccess.open(fullpath, FileAccess.WRITE)
if file == null:
push_error("@FileManager.SetDictionaryAsFile. File (", fullpath ,") failed to be opened for write.")
push_error("Error: ", FileAccess.get_open_error())
file.store_string(string)
file.close()
file = null
and
#User Save States
const ProfilesDirectory : String = "user://Profiles/DemoProfile/" #AppData\Roaming\Godot\app_userdata\[ProjectNameHere]\Profiles\DemoProfile
const ProfileFilename : String = "Profile1.txt"
Basically using a recursive directory creation, and writing user created / edited data to ‘user://’
Relevant reading:
DirAccess
UserDirectory
1 Like