alexcrichton / tar-rs

Tar file reading/writing for Rust
https://docs.rs/tar
Apache License 2.0
616 stars 178 forks source link

Failed to read Entry into memory #323

Closed kaphula closed 1 year ago

kaphula commented 1 year ago

Not sure if I am using this correctly but I cannot read entries from a tar file into memory because the read call fills my Vec<u8> every time with 0 bytes:

    let file = File::open(DATA_FILE).expect("Failed to open data file!");
    let mut archive = Archive::new(file);
    let mut assets = vec![];
    let entries = archive.entries().expect(format!("Failed to open data file: {}", DATA_FILE).as_str());
    for file in entries {
        match file {
            Ok(mut ok) => {
                let filename = {
                    let tmp = ok.path().expect("Failed to get data entry filename!").clone();
                    tmp.to_str().expect("cannot convert path to str").to_string()
                };
                if filename.ends_with(".png") {
                    let mut data: Vec<u8> = vec![];
                    ok.read(&mut data); // 0 bytes every time?
                    assets.push(
                        RawAsset { raw_data: data, filename: filename.to_string(), asset_type: AssetType::ImagePng }
                    );
                }
            }
            Err(err) => {
                panic!("Failed to read data entry: {}", err)

            }
        }
    }

Is this how you are supposed to use this library? The example extract_file.rs uses copy to copy the bytes but I cannot use that in my case because of a trait error.

NobodyXu commented 1 year ago

This line:

ok.read(&mut data); // 0 bytes every time?

"data" is an empty Vec and you basically pass a empty slice into read, so of course it will always returns 0.

Also, read is not guaranteed to read all data from the file.

You need to use read_to_end instead:

ok.read_to_end(&mut data).unwrap();
kaphula commented 1 year ago

Thanks! What do you mean it is not guaranteed to read all data from the file? How can I guarantee that each file's data will be read correctly?

NobodyXu commented 1 year ago

Just use read_to_end as I have shown you, it will guarantee that.

NobodyXu commented 1 year ago

@kaphula I recommend you to read the doc for std::io::Read, it will clear things up for you.

kaphula commented 1 year ago

Yes I did. If I understood correctly matching the result of ok.read_to_end will catch all possible errors if something goes wrong, and if no errors are found and Ok is returned, all data is loaded correctly. Is this correct?

NobodyXu commented 1 year ago

Yes I did. If I understood correctly matching the result of ok.read_to_end will catch all possible errors if something goes wrong, and if no errors are found and Ok is returned and all data was loaded correctly. Is this correct?

yes, that's correct.

kaphula commented 1 year ago

Thanks for the help!