0
votes

i'm trying to decompress a file in memory using GZipStream, copy the decompressed data to a MemoryStream, and then read the MemoryStream using BinaryReader (from Unity 3d). However, i get these errors when i try to run it:

EndOfStreamException: Failed to read past end of stream. System.IO.BinaryReader.FillBuffer (Int32 numBytes) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:119) System.IO.BinaryReader.ReadInt32 () (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/BinaryReader.cs:432) LoadNii.LoadNifti (System.String fullPath, Boolean loadFromResources) (at Assets/scripts/LoadNii.cs:240) opengl_main.PrepareNewAnatomy (System.String fullPath, Boolean loadFromResources) (at Assets/scripts/opengl_main.cs:193) opengl_main.LoadFileUsingPath () (at Assets/scripts/opengl_main.cs:656) UnityEngine.Component:SendMessage(String, Object) SimpleFileBrowser.Scripts.GracesGames.FileBrowser:SendCallbackMessage(String) (at Assets/Resources/SimpleFileBrowser/Scripts/GracesGames/FileBrowser.cs:274) SimpleFileBrowser.Scripts.GracesGames.FileBrowser:SelectFile() (at Assets/Resources/SimpleFileBrowser/Scripts/GracesGames/FileBrowser.cs:267) UnityEngine.EventSystems.EventSystem:Update()

anyone know what the problem is? is there another way to unzip a file in memory, and transfer it to a binaryReader? thanks

code:

Stream stream = null;
if (loadFromResources == true)
{
    TextAsset textAsset = Resources.Load(fullPath) as TextAsset;
    Debug.Log(textAsset);
    stream = new MemoryStream(textAsset.bytes);
}
else
{
    FileInfo fi1 = new FileInfo(fullPath);
    if (fi1.Extension.Equals(".gz"))
    {
        stream = new MemoryStream();
        byte[] buffer = new byte[4096];

        using (Stream inGzipStream = new GZipStream(File.Open(fullPath,FileMode.Open), CompressionMode.Decompress))
        {
            int bytesRead;
            while ((bytesRead = inGzipStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, bytesRead);
            }
        }

    }
    else
        stream = File.Open(fullPath, FileMode.Open);
}
using (BinaryReader reader = new BinaryReader(stream))
{
    //header headerKey substruct:
    headerKey.sizeof_hdr = reader.ReadInt32(); //ERROR
}
2

2 Answers

3
votes

Each time you write to a stream, its Position is increased.

Just set stream.Position = 0 after writing to it, so that you'll start reading from the first byte again afterwards.

0
votes

This is just a function that deserializes and get your result back. Thank you @C.Evenhuis.

          /// <summary>
         ///Get data from a binary file.
        /// </summary>
       /// <param name="filename"></param>
      /// <param name="path"></param>
     /// <returns>Null if no object is found </returns>
        public static T GetData<T>(string filename, string path)
        {
            //Path is empty.
            if (string.IsNullOrEmpty(path)) throw new NullReferenceException("Path can not be null or empty");

            //file is empty.
            if (string.IsNullOrEmpty(filename)) throw new NullReferenceException("File name can not be null or empty.");


            //Storage path
            var storagePath = Path.Combine(path, filename);

            //check file not exist
            if (!File.Exists(storagePath))
                throw new NullReferenceException("No file with the name " + filename + "at location" + storagePath);
            else
                try
                {
                    //create new binary formatter .
                    BinaryFormatter binaryFormatter = new BinaryFormatter();
                    //Read the file.
                    using (FileStream fileStream = File.Open(storagePath, FileMode.Open))
                    {
                        //result .
                        var result = binaryFormatter.Deserialize(fileStream);
                        //Set file stream to zero .
                        //to avoid Exception: FailedSystem.IO.EndOfStreamException: 
                        //Failed to read past end of stream.
                        fileStream.Position = 0;
                        //Check if casting is possible and raise error accordin to that .
                        return (T)Convert.ChangeType(binaryFormatter.Deserialize(fileStream), typeof(T));

                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Failed" + ex);
                }
        }