-
-
Notifications
You must be signed in to change notification settings - Fork 19.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open compressed files that were not made by godot #28999
Comments
This comment has been minimized.
This comment has been minimized.
I was trying to load RexPaint images (.xp files) and it seems I'm having the same problem. Error 15, file unrecognized. I'm an ignorant when comes to compression formats, but according to RexPaint's manual:
So I tried |
I also have the same problem. I try to pack some text resources and use it in game. I tried |
To avoid error 15 you need to add header yourself, sadly
And in the end of file for safety:
I pack compressed data + header into temporary file with open() and then read that file with open_compressed() |
@R-033 where does the |
@Skaruts |
@R-033 I'm confused, though. At that point I don't know the size of the decompressed data, or what to expect the size to be. |
@Skaruts usually this value is used for creating output array internally, so maybe if you'll make it big enough there won't be a problem? I'm just guessing though, I didn't check godot sources |
Ran into this today. Especially annoying since the compression formats already seem to use magic numbers... |
Note that for this particular use case, transparent gzip compression is now supported in HTTPRequest in the |
It looks like there is a maximum block size for compressed data, and the |
I wrote a little program to compress files outside of Godot, which can then be loaded normally inside Godot: It also gets way better compression ratios for some files, with the downside that Godot will decompress the entire file at once. |
I had to do some trial and error, but I was able to use the advice in this thread to successfully get Godot to read a file that was externally compressed. |
I tried opening NBT files (in my case Minecraft schematics) which are documented as being some binary data wrapped in GZIP. 7zip can open the file just fine (also indicates there is a 10 bytes header), so there is surely a way to recognize its format. So far I just see that After fiddling around, in the end it looks like this worked: compressed_data = FileAccess.get_file_as_bytes(fpath)
var decompressed_data := compressed_data.decompress_dynamic(-1, FileAccess.COMPRESSION_GZIP) Of course if the file comes from malicious players you should specify The following is some fiddling around I did, before I noticed GZIP was just working (I was trying hard with DEFLATE instead but got nowhere). I gave a try reading the GZIP format myself, and handling the compressed data to Here is the code I have so far: static func open_gzip(fpath: String) -> PackedByteArray:
var f := FileAccess.open(fpath, FileAccess.READ)
if f == null:
push_error("Could not open file ", fpath, ", error ", FileAccess.get_open_error())
return PackedByteArray()
# https://docs.fileformat.com/compression/gz/
# Read 10-byte header
var header := f.get_16() # 1f 8b
var compression_method := f.get_8() # 08 for DEFLATE
var file_flags := f.get_8()
var timestamp := f.get_32()
var compression_flags := f.get_8()
var os_id := f.get_8()
# Assuming no other extra header stuff, which my file doesn't have,
# but might need to be handled eventually
var compressed_data_position := f.get_position()
print("compressed_data_position ", compressed_data_position)
var total_file_length := f.get_length()
var footer_length := 8
var compressed_data_size := total_file_length - compressed_data_position - footer_length
var compressed_data := f.get_buffer(compressed_data_size)
# Read footer
var checksum_crc32 := f.get_32()
var decompressed_data_size := f.get_32()
print(f.get_position())
print("decompressed_data_size ", decompressed_data_size)
print("CRC32 ", checksum_crc32)
f = null
#compressed_data = FileAccess.get_file_as_bytes(fpath)
# Decompress data ourselves. Usually the format is DEFLATE.
# Godot allows to specify either GZIP or DEFLATE, but there is no difference in the
# implementation.
var decompressed_data := compressed_data.decompress_dynamic(-1, FileAccess.COMPRESSION_DEFLATE)
print("decompressed_data.size(): ", decompressed_data.size())
return decompressed_data And the file I'm testing with, just in case (inside zip) |
Godot version: 33897d9
OS/device including version: Linux 4.14.113-1-MANJARO
Issue description:
I was trying to load a gzipped json file from an external web server, and found out that I can't seem to find a way to do so in godot without making a gdnative plugin. File has the method open_compressed() which supports gzip, but the format it expects for gzip has this bizarre gcpf magic header that encapsulates the format.
![Screenshot_2019-05-19_05-54-52](https://user-images.githubusercontent.com/4523300/57981522-24f1ef00-79fe-11e9-9db8-dea7fc1e3c1c.png)
I kind of expected that it would at the very least open up compressed files that weren't made using the godot editor, assuming encryption wasn't used, considering at the end of the day it's just a bunch of strings or whatever other bytes in there. I'm not sure why the magic header exists in the compression format, but ideally if it could fall back to not requiring the magic header at all and just open up the file without it instead that would be cool.
If I ever need to edit a gzipped file that godot has made i can't just do a quick change from any other archive tools, i'll have to open up godot, open it up, edit it, and then re-export it in order for godot to continue being able to read it which is kind of annoying.
Steps to reproduce:
Minimal reproduction project:
test_compression.zip
user://test.json.gz
, and load it with "load gz". you can use this to compare the output that godot is expecting compared to the output from command-line gzipThe text was updated successfully, but these errors were encountered: