locked
Using compressor and decompressor with datareader and datawriter

    Question

  • I've been trying to use the Compressor and Decompressor classes to write app data. To get started I tried to store a simple string.

    Compressing the data seems to go fine:

    using (var stream = await pickedFile.OpenAsync(FileAccessMode.ReadWrite))
    using (var compressor = new Compressor(stream))
    using (var writer = new DataWriter(compressor))
    {
        string stringToWrite = "This is a test string";
        writer.WriteInt32(stringToWrite.Length);
        writer.WriteString(stringToWrite);
        await writer.StoreAsync();
        await stream.FlushAsync();
    }

    however, I can't get this file decompressed. Straight forward inverting the write process files as follows doesn't seem to work (error details follow):

    using(var readFile = await storageFile.OpenAsync(FileAccessMode.Read))
    using(var decompressor = new Decompressor(readFile))
    using (var reader = new DataReader(decompressor))
    {
    	await reader.LoadAsync((uint) readFile.Size);                    
    	var length = reader.ReadInt32();
    	var text = reader.ReadString((uint)length);
    	LocaleTextBlock.Text = text;
    }

    So when that failed, I tried using a RandomAccessStream, which more closely follows the sample from the SDK. However, this also failed.

    using(var readFile = await storageFile.OpenSequentialReadAsync())
    using(var decompressor = new Decompressor(readFile))
    using (var memoryStream = new InMemoryRandomAccessStream())
    {
    	var resultWrite = await RandomAccessStream.CopyAsync(decompressor, memoryStream);
    	memoryStream.Seek(0);
    	using (var reader = new DataReader(memoryStream))
    	{
    		var readResult = await reader.LoadAsync((uint) memoryStream.Size);
    		var length = reader.ReadInt32();
    		var text = reader.ReadString((uint) length);
    		LocaleTextBlock.Text = text;
    	}
    }

    Both decompress attempts fail. In the seconds attempt you can already see it failing by inspecting the resultWrite variable, that should contain a non-zero number indicating the number of bytes written. However it is zero.

    Finally both examples fail with an exception when during the reader.ReadInt32 call, with the following message:

    Additional information: The operation attempted to access data outside the valid range (Exception from HRESULT: 0x8000000B).

    To confirm that it is related to the Compressor/Decompressor logic, I once removed the compression and decompression parts and everything was fine.

    I've been stuck at this for a while now, any help is very much appreciated!



    • Edited by Edsger Monday, August 18, 2014 7:04 AM typo
    Wednesday, August 13, 2014 10:12 PM

All replies

  • Hi Edsger,

    I would suggest you to download a Compress/Decompress sample from code center: http://code.msdn.microsoft.com/windowsapps/Compression-sample-9d57900f

    Your second code snippet works fine with me, here is my code, I can see the size of resultWriter is not 0:

                    using (var compressedInput = await compressedFile.OpenSequentialReadAsync())
                    using (var decompressor = new Decompressor(compressedInput))
                    using (var memoryStream = new InMemoryRandomAccessStream())
                    {
                        var resultWrite = await RandomAccessStream.CopyAsync(decompressor, memoryStream);
                        memoryStream.Seek(0);
                        using (var reader = new DataReader(memoryStream))
                        {
                            var readResult = await reader.LoadAsync((uint)memoryStream.Size);
                            var length = reader.ReadInt32();
                            var text = reader.ReadString((uint)length);
                            Progress.Text = text;
                        }
                    }

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Thursday, August 14, 2014 8:06 AM
    Moderator
  • Seems you update your question.

    For saving or reading data via DataReader, you may ref to Quickstart: Reading and writing files. If you need to get the length of the file, probably you may need following code:

                        DataReader dataReader = new DataReader(inputStream);
                        uint length = await dataReader.LoadAsync((uint)size);
                        string text = dataReader.ReadString(numBytesLoaded);
    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Thursday, August 14, 2014 8:16 AM
    Moderator
  • Thanks for your help.

    You confirm that it works in you solution. However, I still don't know how to get mine working? What's the difference between our code? Can it still have something to do with the write logic?

    In your second post you refer to a size. However that's not possible and also the reason for my second read attempt using the RandomAccessStream. The Datareader uses the stream from the Decompressor and this stream can of course have a different size as the filestream because of decompression. So using number of bytes from the filestream for the LoadAsync would be incorrect, furthermore the Decompressor doesn't supply a Size.


    • Edited by Edsger Thursday, August 14, 2014 9:25 AM
    Thursday, August 14, 2014 9:23 AM
  • Hi Edsger,

    I use the sample from code center and paste your code in, I would suggest you to share your code with me to have a look what's the difference.

    For the second one, I agree with you, the stream from Decompressor must have a different size and but I consider we can save decompressor file to somewhere and the file size should be correct.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Thursday, August 14, 2014 11:46 AM
    Moderator
  • Hello James,

    I created a Git repository in the public domain so you should be able to access it. If you aren't using Git yourself you can use the download-as-zip option to get the code directly.

    Here's the link:

    https://github.com/freeknossin/examples/

    Thursday, August 14, 2014 6:03 PM
  • Hello James,

    I created a Git repository in the public domain so you should be able to access it. If you aren't using Git yourself you can use the download-as-zip option to get the code directly.

    Here's the link:

    https://github.com/freeknossin/examples/

    Would somebody be so kind to have a look at this?

    Thanks!

    Monday, August 18, 2014 11:06 AM
  • Anybody willing to help?

    Thanks!

    Thursday, August 21, 2014 8:06 AM