zoukankan      html  css  js  c++  java
  • 提高sevenzipsharp 检查密码的速度(1)

    前言:sevenzipsharp检查密码(包括检查压缩包的有效性)的函数是SevenZipExtractor.check(), sevenzipsharp调用的是7zip的动态链接库,而且不止是7zip,其它压缩软件测试密码这个功能耗时也很久(压缩包小可以忽略,密码错误的时候速度还行,密码正确的话,会把压缩包全部解压,耗时相当于解压一个文件的时间),除了360压缩比较快,至少快几百倍,但是找不到调用的方法,如果谁有更好的解决方案,麻烦提供一下。

    原来的check方法4G大小的文件大概耗时

    错误的密码:www.cr173.com用时:0.19秒
    正确的密码:www.he11oworld.com用时:85.98秒

    方案1:我的思路是既然检测一个压缩包的解压密码,没必要把所有的文件都检测一遍,取压缩包最小的加密文件去检测就行了,4G大小的文件大概耗时

    错误的密码:www.cr173.com用时:0.19秒
    正确的密码:www.he11oworld.com用时:26.18秒

    方案2:同样是检查一个文件,检查第一个加密文件,,4G大小的文件大概耗时

    错误的密码:www.cr173.com用时:0.12秒
    正确的密码:www.he11oworld.com用时:0.10秒

    发现方案二是最优的,一下是具体实现的代码

    定义一个全局字段,用来存取压缩包内最小的文件索引和大小

    private IDictionary<int, ulong> encryptionFileInfo = null;

    初始化窗体时实例化

    encryptionFileInfo = new Dictionary<int, ulong>();

    获取压缩包信息时,保存最小文件的索引和大小

    encryptionFileInfo.Clear();
    foreach (ArchiveFileInfo item in extr.ArchiveFileData)
                    {
                        if (item.Encrypted)
                        {
                            if (encryptionFileInfo.Count == 0)
                            {
                                encryptionFileInfo.Add(item.Index, item.Size);
                            }
                            ////只检测最小文件的实现方法
                            //else
                            //{
                            //    if (encryptionFileInfo.Values.ElementAt(0) > item.Size)
                            //    {
                            //        encryptionFileInfo.Clear();
                            //        encryptionFileInfo.Add(item.Index, item.Size);
                            //    }
                            //}
                        }
                    }

    实现优化函数,在SevenZipExtractor.cs单元添加函数如下函数

    /// <summary>
            /// 检查压缩包密码
            /// </summary>
            /// <param name="minFileIndex">压缩包中加密文件索引最小的值</param>
            /// <returns></returns>
            public bool Check(int minFileIndex)
            {
                DisposedCheck();
                try
                {
                    InitArchiveFileData(false);
                    var archiveStream = GetArchiveStream(true);
                    var openCallback = GetArchiveOpenCallback();
                    if (!OpenArchive(archiveStream, openCallback))
                    {
                        return false;
                    }
                    using (var aec = GetArchiveExtractCallback("", (int)_filesCount, null))
                    {
                        try
                        {
                            uint[] u = new uint[1];
                            u[0] = uint.Parse(minFileIndex.ToString());
                            CheckedExecute(
                                                        _archive.Extract(u, 1, 1, aec),
                                                        SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec);
                            //CheckedExecute(
                            //    _archive.Extract(null, UInt32.MaxValue, 1, aec),
                            //    SevenZipExtractionFailedException.DEFAULT_MESSAGE, aec);
                        }
                        finally
                        {
                            FreeArchiveExtractCallback(aec);
                        }
                    }
                }
                catch (Exception)
                {
                    return false;
                }
                finally
                {
                    if (_archive != null)
                    {
                        _archive.Close();
                    }
                    ((InStreamWrapper)_archiveStream).Dispose();
                    _archiveStream = null;
                    _opened = false;
                }
                return true;
            }

    之后就是调用了,

    using (SevenZipExtractor extr = new SevenZipExtractor(tbPackagePath.Text, Convert.ToString(item["Password"])))
                    {
                        
                        if (extr.Check(index))
                        {
                            tbPassword.Text = Convert.ToString(item["Password"]);
                            memoEdit1.Text = memoEdit1.Text + "此为正确密码:" + Convert.ToString(item["Password"]) + "用时:" + (DateTime.Now - dtStartDetail).TotalMilliseconds.ToString() + "
    ";
                            return;
                        }
                        memoEdit1.Text = memoEdit1.Text + "测试密码:" + Convert.ToString(item["Password"]) + "用时:" + (DateTime.Now - dtStartDetail).TotalMilliseconds.ToString() + "
    ";                    
                    }

     如果只用方案2可以把IDictionary<int, ulong>换成整型

  • 相关阅读:
    Spring优势
    Spring中的设计模式
    Spring MVC体系结构
    《Spring3.0就这么简单》第1章快速入门
    InvocationHandler
    JdkDynamicAopProxy源码
    Proxy代理(AOP实现原理)
    Spring AOP 实现原理
    BeanFactory和ApplicationContext的作用和区别
    背景图片相关设置
  • 原文地址:https://www.cnblogs.com/-Object/p/5376895.html
Copyright © 2011-2022 走看看