PSeitz / lz4_flex

Fastest pure Rust implementation of LZ4 compression/decompression.
MIT License
425 stars 29 forks source link

decompress a `.lz4` file? #158

Open jtmoon79 opened 2 months ago

jtmoon79 commented 2 months ago

I'm trying to use lz4_flex to decompress a small .lz4 file. The file was compressed using lz4c on Ubuntu 22.

$ echo foobar > file

$ lz4c -9kv file
*** LZ4 command line interface 64-bits v1.9.3, by Yann Collet ***
Compressed filename will be : file.lz4
Compressed 7 bytes into 26 bytes ==> 371.43%

However, my various attempts at reading the file file.lz4 using a lz4_flex::frame::FrameDecoder and calls to .read or .read_exact do return Ok. However they do not appear to write anything to the passed Vec<u8>.

My code is

use std::fs::File;
use std::fs::OpenOptions;
use std::io::prelude::Read;
use std::io::BufReader;
use std::path::Path;
use ::lz4_flex;

fn main() {

    let mut open_options = OpenOptions::new();
    let path = String::from("/tmp/file.lz4");
    let path_std = Path::new(&path);
    let file_lz: File = match open_options.read(true).open(path_std) {
        Ok(val) => val,
        Err(err) => panic!("{}", err),
    };
    let mut bufreader = BufReader::<File>::new(file_lz);
    let mut lz4_decoder = lz4_flex::frame::FrameDecoder::new(bufreader);
    let mut buffer = Vec::<u8>::with_capacity(1024);
    let sz = match lz4_decoder.read(&mut buffer) {
    //match lz4_decoder.read_exact(&mut buffer) {
        Ok(_) => {}
        Err(err) => panic!("{}", err),
    };
    eprintln!("buffer: {:?}", buffer);
}

Could you provide an example for decompressing an .lz4 file? Reviewing the examples, it was not obvious to me how to go about this as the examples only use "live" stdin streaming.

PSeitz commented 2 months ago

Can you retry using std::io::copy like in the examples instead of a single read call? https://docs.rs/lz4_flex/latest/lz4_flex/#example-decompress-data-on-stdin-with-frame-format

jtmoon79 commented 2 months ago

Thanks @PSeitz . I got this working. I was not setting the length of the passed buffer (see https://github.com/rust-lang/rust/issues/96915).

This code works (notice the call to resize)

use std::fs::File;
use std::fs::OpenOptions;
use std::io::prelude::Read;
use std::io::BufReader;
use std::path::Path;
use ::lz4_flex;

fn main() {
    let mut open_options = OpenOptions::new();
    let path = String::from("/tmp/file.lz4");
    let path_std = Path::new(&path);
    let file_lz: File = match open_options.read(true).open(path_std) {
        Ok(val) => val,
        Err(err) => panic!("{}", err),
    };
    let bufreader = BufReader::<File>::new(file_lz);
    let mut lz4_decoder = lz4_flex::frame::FrameDecoder::new(bufreader);
    let mut buffer = Vec::<u8>::with_capacity(1024);
    buffer.resize(1024, 0);
    let sz = match lz4_decoder.read(&mut buffer) {
        Ok(sz) => sz,
        Err(err) => panic!("{}", err),
    };
    eprintln!("buffer: {:?}", &buffer[..sz]);
}

If you're interested, I can submit a PR for this at /examples/decompress_file.rs.

PSeitz commented 2 months ago

Yeah a PR would be nice, e.g. /examples/decompress_file_into_vec.rs