Search code examples
phplinuxwindowsxz

Windows equivalent of specific LINUX compression tool


In LINUX there is this very specific compression utility/tool at /usr/bin/xz.

Now I am on Windows 10 x64 running PHP 8.1 and I have a php library, that in one line of its code call this very specific LINUX file (everything else in that code is compatible with the Windows, except this one line of code) with some specific switches setting its parameters. This is the line:

$x = proc_open("/usr/bin/xz '--format=raw' '--lzma1=lc=3,lp=0,pb=2,dict=128KiB' '-c' '-'", [0 => ["pipe", "r"], 1 => ["pipe", "w"]], $p);

What I am trying to find is some Windows equivalent utility that I could substitute that LINUX one for, that would accept some similiar switches for setting its attributes, wording may be different - it would be no problem, I would just change them accordingly.

I thought, that windows XZ Utils might be just that, but unfortunately, their xz.exe does not accept any switches that would set its attributes as LINUX file does.

Is there some Windows app (or maybe php script even?) that would do lzma1 data compression similiar to LINUX /usr/bin/xz that I could use under Windows?


Solution

  • Here's my version of your code, hopefully the comments add some clarity.

    First, I didn't download the file you requested, I used the one from here: https://tukaani.org/xz/old.html#_windows

    Second, my version assumes that the PHP script and the xz.exe file live in the same folder. If that's not the case for you, try my version first, then try to figure out how to change the path.

    Third, my version was tested on the CLI only, I don't have the ability to run PHP on my Windows machine (except through WSL).

    Fourth, this code writes some sample text to stdin and compresses that, and if that is successful it outputs the binary text (which is worthless, but shows it is working). Normally you'd save this to disk or base64 encode or something else.

    <?php
    
    // Variable for the current directory
    $dir = __DIR__;
    
    // Absolute path to the binary. This code assumes that it is in the
    // same folder as this PHP script.
    $xz = $dir . DIRECTORY_SEPARATOR . 'xz';
    
    // Pipes to read/write to
    $descriptorspec = [
       0 => ["pipe", "r"],
       1 => ["pipe", "w"],
       2 => ["pipe", "w"],
    ];
    
    // Open the process. Use the array format so that automatic
    // escaping is handled for you.
    $process = proc_open(
        [
            $xz,
            '--format=raw',
            '--lzma1=lc=3,lp=0,pb=2,dict=128KiB',
            '-c',
            '-',
        ],
        $descriptorspec,
        $pipes
    );
    
    // Make sure the above worked
    if(!$process){
        throw new RuntimeException('Could not open proc');
    }
    
    // Write some text to the stream to compress. You could also use
    // file_get_contents or one of the command line switches
    fwrite($pipes[0], 'This is a test');
    
    // We're done writing
    fclose($pipes[0]);
    
    // Grab the contents of stdout and stderr
    $output = stream_get_contents($pipes[1]);
    $error  = stream_get_contents($pipes[2]);
    
    fclose($pipes[1]);
    fclose($pipes[2]);
    
    // Clean up
    if(!$return_value = proc_close($process)){
        // Successfully ran the command, do something with $output
        echo 'Output:', PHP_EOL, $output;
    }else{
        echo 'There was an error, the command returned: ' . $return_value;
        echo PHP_EOL;
        echo $error;
    }