adamhathcock / sharpcompress

SharpCompress is a fully managed C# library to deal with many compression types and formats.
MIT License
2.25k stars 479 forks source link

open zip file has error with the zip date in file has a offset #85

Closed andyhebear closed 8 years ago

andyhebear commented 9 years ago

i wite a file with a head pack and then wite the zip file after,but when i read this file to seek the zip date start position,then throw error!!!

adamhathcock commented 9 years ago

More detail or a sample would be great

andyhebear commented 9 years ago

i write a recorder data ,then i need some file info in file head public const string IRQ_RECODER_HEARD = "therecoder"; like code: // the file header public class RecoderHeader { public string RECODER_HEARD = IRQ_RECODER_HEARD;

        public string Version ="1.1";
        public string Author="Rains";
        /// <summary>
        /// ID
        /// </summary>
        public int UserId="10086";
        public DateTime RecoderTime = DateTime.Now;
        //
        public string MissionName;
        public int FrameCount;
        public short IRQObjectsCount;
        public byte RobotCount;
        public float MissionTime;

        public string[] ResIds;

        public string RobotPackageUniqueId = "";
    }

const int HEAD_LENGTH=1024*4+32;

private static byte[] CreateHead() {

        byte[] buf = null;
        using (MemoryStream ms = new MemoryStream()) {
            using (BinaryWriter bw = new BinaryWriter(ms)) {
                bw.Write(System.Text.Encoding.UTF8.GetBytes(HeadInfo.RECODER_HEARD));          //the head flag
                bw.Write(new byte[32]);//MD5

                bw.Write(HeadInfo.Version);                //ver
                bw.Write(Convert.ToBase64String(Encoding.UTF8.GetBytes(HeadInfo.UserId.ToString())));//author id
                bw.Write(Convert.ToBase64String(Encoding.UTF8.GetBytes(HeadInfo.Author)));                  //author name
                bw.Write(HeadInfo.RecoderTime.ToBinary());  //long 
                bw.Write(HeadInfo.MissionName);             //
                bw.Write(HeadInfo.FrameCount);              //
                bw.Write(HeadInfo.MissionTime);
                bw.Write(HeadInfo.RobotCount);
                bw.Write(HeadInfo.IRQObjectsCount);
                if (HeadInfo.ResIds == null || HeadInfo.ResIds.Length == 0) {
                    bw.Write((ushort)0);
                }
                else {
                    bw.Write((ushort)HeadInfo.ResIds.Length);
                    for (int i = 0; i < HeadInfo.ResIds.Length; i++) {
                        bw.Write(HeadInfo.ResIds[i]);
                    }
                }
                //1.5.2.0
                bw.Write(HeadInfo.RobotPackageUniqueId);
            }
            buf = ms.ToArray();
        }
        //
        int len = (buf.Length > HEAD_LENGTH) ? buf.Length : HEAD_LENGTH;
        byte[] buf2 = new byte[len];
        Array.Copy(buf, buf2, buf.Length);
        return buf2;
    }
    //write header in file first
    private static void WriteHeadInfo(BinaryWriter bw) {
        byte[] buf = CreateHead();//userid, author, missionname);
        bw.Write((ushort)buf.Length);//
        bw.Write(buf, 0, buf.Length);
    }

   // read file by has my head flag data
    public static bool ReadHeadInfoFromFile(string recordzipfilepath) {
        bool ok = false;

        using (FileStream fs = new FileStream(recordzipfilepath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
            //
            using (BinaryReader br = new BinaryReader(fs)) {
                ok = ReadHeadInfo(br);
                if (ok) {
                    //readScore(br);
                }
            }
        }
        return ok;
    }

private static bool ReadHeadInfoFromFile(string recordzipfilepath, out FileStream fs) { bool ok = false; fs = new FileStream(recordzipfilepath, FileMode.Open, FileAccess.Read, FileShare.Read); { //read head info BinaryReader br = new BinaryReader(fs); { ok = ReadHeadInfo(br); if (ok) { //readScore(br); } } } return ok; }

///

    /// read file zip date by with header data
    /// </summary>

    /// <param name="recordzipfilepath"></param>
    /// <returns></returns>
    public static bool LoadFromZFile(string recordzipfilepath) {
        FileStream fs = null;
        try {
            //ReadHeadInfoFromFile(recordzipfilepath);
            if (ReadHeadInfoFromFile(recordzipfilepath, out fs) == false) {
                return false;
            }
            m_RecordToSaveTemp_OverFrameSaveNumberFlag = HeadInfo.FrameCount;
            //using (FileStream fs = new FileStream(recordzipfilepath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
            //    fs.Position = HEAD_LENGTH + 2 ;//长度占2个字节 
            //read data from compress data after header
            using (SharpCompress.Archive.Zip.ZipArchive zip = SharpCompress.Archive.Zip.ZipArchive.Open(fs, null)) {
                foreach (var v in zip.Entries) {
                    using (FileStream fsw = new FileStream(m_PlaybackTempFile, FileMode.Create)) {
                        Stream s = v.OpenEntryStream();
                        byte[] buf = new byte[1024 * 64];
                        int rc = 0;
                        while ((rc = s.Read(buf, 0, buf.Length)) > 0) {
                            fsw.Write(buf, 0, rc);
                        }
                        //
                        break;
                    }
                }
            }

            return true;
        }
        catch (Exception ee) {
            DebugLog.Log("err:", ee);
            return false;
        }
        finally {
            if (fs != null) {
                fs.Close();
                fs = null;
            }
        }
        return false;
    }
andyhebear commented 9 years ago

the save like:
public static bool SaveToZFile(string filename) {

        bool ok = false;
        using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) {
            //using (GZipStream instream = new GZipStream(fs, CompressionMode.Compress)) {//
            using (BinaryWriter bw = new BinaryWriter(fs)) {
                ok = SaveTo(bw);
            }
        }
        return ok;
    }
 static bool SaveTo(BinaryWriter bw) {

        //
        //head flag
        WriteHeadInfo(bw);
        //
       string m_RecordTempFileName="temp.tmp";
        //zip  Deflate          
        using (FileStream fs = new FileStream(m_RecordTempFileName, FileMode.Open, FileAccess.ReadWrite)) {
            using (SharpCompress.Archive.Zip.ZipArchive za = SharpCompress.Archive.Zip.ZipArchive.Create()) {
                SharpCompress.Common.CompressionInfo ci = new SharpCompress.Common.CompressionInfo();
                //ci.DeflateCompressionLevel = SharpCompress.Compressor.Deflate.CompressionLevel.Default;
                ci.Type = SharpCompress.Common.CompressionType.Deflate;
                za.AddEntry("video.dat", fs, fs.Length, null);
                _sharpCompress_oldSaveBytes = 0;
                za.CompressProgress += new EventHandler<SharpCompress.Archive.CompressProgressEventArgs>(za_CompressProgress);
                za.SaveTo(bw.BaseStream, ci);
                //写md5
                int marksize = IRQ_RECODER_HEARD.Length;
                bw.BaseStream.Position = 2 + marksize + 32;//长度+标识+32字节的MD5(真正的MD5是16字节)
                byte[] buf = IRobotQ.Base.Utility.IRQ_Utility.GetStreamMD5(bw.BaseStream);
                bw.BaseStream.Position = 2 + marksize;
                bw.Write(buf);
                //剩余16字节,随机
                Random rnd = new Random();
                rnd.NextBytes(buf);
                bw.Write(buf);
            }
        }

        return true;

}

andyhebear commented 9 years ago

the code is long in my project, the sample save file: 1:write headdata 2:write compress data and the read the save file 1: read headdata,and the stream has a position 2: read compress data in filestream and decompress ,and then throw error...

adamhathcock commented 9 years ago

Sorry, this is not making any sense to me.

Give me a valid zip file that errors out when SharpCompress reads it.

andyhebear commented 8 years ago

//ok! I write a test again: // please test using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using SharpCompress.Archive; using SharpCompress.Archive.Zip; using SharpCompress.Common;

namespace SharpCompress { static class _TestSharpCompress { public static void Main(string[] args) {

       //please create a dir "ziptest" and add some files,you will can run this program
        string SCRATCH_FILES_PATH = "ziptest";
        string scratchPath = "ziptest.zip";

         using (var archive = ZipArchive.Create()) 
         { 
             archive.AddAllFromDirectory(SCRATCH_FILES_PATH); 
             archive.SaveTo(scratchPath, CompressionType.Deflate); 
         }
        //write my zipfile with head data
         using (FileStream fs = new FileStream("mypack.data.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) {
             MyHead mh = new MyHead();
             byte[] headData = mh.Create();
             fs.Write(headData, 0, headData.Length);
             using (FileStream fs2 = new FileStream(scratchPath, FileMode.Open, FileAccess.Read)) {
                 byte[] buf = new byte[1024];
                 int rc=0;
                 while( (rc= fs2.Read(buf, 0, buf.Length)) >0){
                     fs.Write(buf, 0, rc);
                 }
             }
         }
        //
        //read my zip file with head
        //
         using (FileStream fs = new FileStream("mypack.data.zip", FileMode.Open, FileAccess.Read, FileShare.Read)) {
             byte[] buf = new byte[1024];
             int offset=fs.Read(buf, 0, buf.Length);
             System.Diagnostics.Debug.Assert(offset==1024);
             ZipArchive zip=ZipArchive.Open(fs, Options.LookForHeader);//cann't read
             //ZipArchive zip = ZipArchive.Open(fs, Options.None); //will throw exption
             //ZipArchive zip = ZipArchive.Open(fs, Options.KeepStreamsOpen);//cann't read
             foreach (ZipArchiveEntry zf in zip.Entries) {
                 Console.WriteLine(zf.Key);
                 //bug:none key in zipfile
             }
         }
    }
    public class MyHead {
        public int Id = 10086;
        public string Ver = "1.0.1";
        public string Flag = "MyHead";
        public byte[] Create() {
            byte[] buf = null;
            using (MemoryStream ms = new MemoryStream(1024)) {
                ms.SetLength(1024);
                using (BinaryWriter bw = new BinaryWriter(ms, Encoding.UTF8)) {
                    bw.Write(this.Flag);
                    bw.Write(this.Id);
                    bw.Write(this.Ver);

                }

                buf = ms.ToArray();
            }
            return buf;
        } 
    }
}

} // https://github.com/RainsSoft/sharpcompress/blob/master/SharpCompress/ziptest.zip you can uncompress "ziptest.zip" to ziptest dir,and run this test

https://github.com/RainsSoft/sharpcompress/blob/master/SharpCompress/mypack.data.zip the compress file "mypack.data.zip" you can open in winrar.exe,but in this test cann't read!!!!

the code you can find in: https://github.com/RainsSoft/sharpcompress/blob/master/SharpCompress/_TestSharpCompress.cs

..

andyhebear commented 8 years ago

the compress file "mypack.data.zip" you can open in winrar.exe,but in this test cann't read!!!! i think the ZipArchive load the stream with not support in a start postion