How do I extract arbitrary files from internal res:// file system into host file system or user://?

Let’s say I have file res://picture.png and I want to extract it either to the user:// filesystem or to the host FS (e.g. next to the executable). Note that “picture.png” might be just as well “sound.ogg” or “randomfile.xyz” - point is I want an ability to extract an arbitrary file into user’s system from the res:// file system. How do I do that?

Does DirAccess.copy not work?

Sadly, no. It returns “File not Found” error.

This is the function I use:

func ExtractFileNextToExe(filename:String):
	var err:Error=DirAccess.copy_absolute(filename,OS.get_executable_path()+"/"+filename.get_file(),744)
	DebugPrint(error_string(err))

(DebugPrint just outputs the thing to both Godot’s console and in-game console). And here’s how I’m calling it:

Globals.ExtractFileNextToExe("res://image.png")

And yes, image.png does exist in the project’s folder.

Obviously, it is to be called from the exported EXE file with internalized PCK.

So, added some more debugging, and it turns out that I have to import image in special way so it gets preserved in the PCK, however even with that present and the function now being

func ExtractFileNextToExe(filename:String):
	var dir:=DirAccess.open("res://")
	var err:Error=dir.copy(filename,OS.get_executable_path()+"/"+filename.get_file(),744)
	DebugPrint(error_string(err))
	DebugPrint(dir.get_files())

it still fails to copy the file over with File Not Found error (even though the file is present in the directory listing shown with the last DebugPrint statement).

The function is now

func ExtractFileNextToExe(filename:String):
	var dir:=DirAccess.open(filename.get_base_dir())
	DebugPrint(filename.get_base_dir())
	var err:Error=dir.copy(filename.get_file(),OS.get_executable_path().get_base_dir()+"/"+filename.get_file(),744)
	DebugPrint(error_string(err))
	DebugPrint(dir.get_files())
	DebugPrint("")
	DebugPrint(filename.get_file())
	DebugPrint(OS.get_executable_path().get_base_dir()+"/"+filename.get_file())

and everything seem to check out (all paths are correct, the file is in the listing of dir.get_files() and so on) but it still fails to copy with “file not found” error.

Well, this just gets better and better.
I’ve added the following line to the above function and it returns true:

DebugPrint(dir.file_exists(filename.get_file()))

SO WHY IS IT FILE NOT FOUND WHEN TRYING TO COPY IT?!

Okay, went the hard way and it works:

func ExtractFileNextToExe(filename:String):
	var inFile:=FileAccess.open(filename,FileAccess.READ)
	var outFile:=FileAccess.open(OS.get_executable_path().get_base_dir()+"/"+filename.get_file(),FileAccess.WRITE)
	var buffer:=inFile.get_buffer(inFile.get_length())
	outFile.store_buffer(buffer)
	outFile.flush()
	outFile.close()
	inFile.close()

But why does DirAccess.copy and DirAccess.copy_absolute don’t work even when the file is right there I still don’t know.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.