ฉันจะสร้างไฟล์เก็บถาวร 7-Zip ด้วย. NET ได้อย่างไร


102

ฉันจะสร้างไฟล์เก็บถาวร 7-Zip จากแอปพลิเคชันคอนโซล C # ได้อย่างไร ฉันต้องสามารถแยกไฟล์เก็บถาวรโดยใช้โปรแกรม7-Zipปกติที่มีอยู่ทั่วไป


นี่คือผลลัพธ์ของฉันพร้อมตัวอย่างที่ให้ไว้เป็นคำตอบสำหรับคำถามนี้

  • "ปลอกกระสุนออก" เพื่อ 7z.exe - นี้เป็นวิธีที่ง่ายและมีประสิทธิภาพมากที่สุดและผมสามารถยืนยันได้ว่ามันใช้งานได้เป็นอย่างดี ตามที่workmad3 กล่าวไว้ฉันแค่ต้องรับประกันว่า 7z.exe ได้รับการติดตั้งบนเครื่องเป้าหมายทั้งหมดซึ่งเป็นสิ่งที่ฉันสามารถรับประกันได้
  • 7Zip ในการบีบอัดหน่วยความจำ - หมายถึงการบีบอัดคุกกี้ "ในหน่วยความจำ" ก่อนส่งไปยังไคลเอนต์ วิธีนี้ดูเหมือนจะค่อนข้างดี วิธีการห่อหุ้ม (ตัดLZMA SDK ) byte[]ประเภทกลับ เมื่อฉันเขียนbyte[]อาร์เรย์ไปยังไฟล์ฉันไม่สามารถแตกโดยใช้ 7-Zip ( File.7z is not supported archive)
  • 7zSharp Wrapper (พบใน CodePlex) - นี่ห่อ 7z exe / LZMA SDK ฉันอ้างอิงโปรเจ็กต์จากแอพของฉันและมันสร้างไฟล์เก็บถาวรบางไฟล์ได้สำเร็จ แต่ฉันไม่สามารถแตกไฟล์โดยใช้โปรแกรม 7-Zip ปกติ ( File.7z is not supported archive) ได้
  • 7Zip SDK aka LZMA SDK - ฉันเดาว่าฉันไม่ฉลาดพอที่จะคิดหาวิธีใช้สิ่งนี้ (ซึ่งเป็นสาเหตุที่ฉันโพสต์ไว้ที่นี่) ... ตัวอย่างโค้ดการทำงานใด ๆ ที่แสดงให้เห็นถึงการสร้างไฟล์เก็บถาวร 7zip ที่สามารถดึงข้อมูลได้โดย โปรแกรม 7zip ปกติ?
  • CodeProject C # (.NET) อินเทอร์เฟซสำหรับ 7-Zip Archive DLLs - รองรับการแยกไฟล์จากไฟล์เก็บถาวร 7zip เท่านั้น ... ฉันต้องสร้างมันขึ้นมา!
  • SharpZipLib - ตามคำถามที่พบบ่อย SharpZipLib ไม่รองรับ 7zip

32
อย่าเขียนว่ามาจาก Google เมื่อลิงค์ทั้งหมดมาจากโพสต์ของฉันด้านล่าง ไม่ค่อยเคารพคนที่ใช้เวลาในการค้นหาวิธีแก้ปัญหาบางอย่างให้คุณ
Patrick Desjardins

3
ฉันรู้ว่าโพสต์นี้เก่า แต่วันนี้ฉันเห็นโครงการชื่อ SevenZipSharp sevenzipsharp.codeplex.com
Timmerz

12
เพียงคำเตือนสำหรับผู้อ่านในอนาคต ดูเหมือนว่า SevenZipSharp จะเป็นเครื่องละทิ้ง ณ วันนี้รุ่นเสถียรล่าสุด (0.64) ได้รับการเผยแพร่ในเดือนสิงหาคม 2010 พร้อมกับปัญหามัลติเธรดที่น่ารังเกียจ (ตามรายงานข้อผิดพลาด) ตั้งแต่นั้นมามีการโพสต์ซอร์สโค้ดเพียงไม่กี่รายการ
Anttu

คำตอบ:


28

หากคุณสามารถรับประกันได้ว่าจะมีการติดตั้งแอป 7-zip (และอยู่ในเส้นทาง) บนเครื่องเป้าหมายทั้งหมดคุณสามารถ offload ได้โดยเรียกใช้แอปบรรทัดคำสั่ง 7z ไม่ใช่วิธีการแก้ปัญหาที่หรูหราที่สุด แต่เป็นการทำงานน้อยที่สุด


7
เราจัดส่งยูทิลิตีบรรทัดคำสั่ง 7z พร้อมกับไบนารีของเราจริง ๆ แล้วส่งออกไป ใช้ได้ดีกับเราจริงๆ
David Mohundro

81

ตัวอย่างคุกกี้ EggCafe 7Zipนี่คือตัวอย่าง (การบีบอัดคุกกี้) ที่มี DLL ของ 7Zip

CodePlex Wrapper นี่คือโครงการโอเพ่นซอร์สที่บิดฟังก์ชันการบีบอัดของ 7z

7Zip SDK SDKอย่างเป็นทางการสำหรับ 7zip (C, C ++, C #, Java) <--- คำแนะนำของฉัน

.Net zip library โดยSharpDevelop.net

ตัวอย่างCodeProjectด้วย 7zip

SharpZipLibหลายซิป


เสร็จสิ้นและฉันได้เพิ่มโครงการโอเพนซอร์สที่มีประโยชน์เช่นกัน
Patrick Desjardins

1
ฮ่า ๆ? เปลี่ยนคุกกี้ด้วยสตริง ... ไฟล์หรืออะไรก็ได้ ... ฮ่า ๆ ?
Patrick Desjardins

1
ไม่ฉันแค่อยากดูว่ามีใครคิดตัวอย่างการทำงานบ้างไหม ... ขอบคุณสำหรับการวิจัยของคุณ แต่ไม่มีลิงก์ใดที่คุณให้มาที่สามารถนำฉันไปสู่สิ่งที่ได้ผล
Seibar

2
ฉันต้องยอมรับว่าไม่มีรหัสที่คุณสามารถคัดลอกและวางได้ SDK คือคำตอบทั้งหมด แต่ต้องใช้เวลาและความพยายามพอสมควรเพื่อให้บางสิ่งได้ผล ฉันเข้าใจคุณไม่ต้องการที่จะทำมัน ขอให้มีความสุขในวันนี้
Patrick Desjardins

3
อย่างไรก็ตามฉันขอแนะนำให้ลบการอ้างอิง SharpDevelop / SharpZipLib เนื่องจากทั้งสองอ้างอิงเหมือนกันและไม่รองรับ 7-Zip Seibar ถามอย่างชัดเจนสำหรับ 7z ฉันกำลังค้นหาโซลูชัน 7z เนื่องจาก ShaprZipLib ไม่ทำงานกับไฟล์เก็บถาวรและพบชุดข้อความนี้ ShaprZipLib เป็นคำใบ้ที่ทำให้เข้าใจผิด!
Onsokumaru

25

SevenZipSharpเป็นอีกหนึ่งโซลูชั่น สร้างไฟล์เก็บถาวร 7 ซิป ...


7
โพสต์นี้โดย markhor มาจากผู้สร้างโครงการ SevenZipSharp SevenZipSharp ช่วยให้สามารถเข้าถึง 7Zip dll แบบเป็นโปรแกรมได้ทำให้มีคุณสมบัติครบถ้วนมาก ฉันพบว่า LZMA SDK อยู่ในระดับต่ำและเข้าใจยาก ตรงกันข้าม SevenZipSharp ได้รับการจัดทำเอกสารอย่างดีใช้งานง่ายและมีตัวอย่างการใช้งานมากมายในโครงการทดสอบ จากตัวอย่างฉันสามารถบีบอัดและคลายการบีบอัดได้อย่างรวดเร็วโดยใช้ไฟล์หรือหน่วยความจำ
John Wigger

4
ดูเหมือนว่า SevenZipSharp จะถูกละทิ้ง ดูความคิดเห็นก่อนหน้าของฉันในคำถาม
Anttu

SevenZipSharp ช้า ในขณะนี้วิธีแก้ปัญหาที่แนะนำที่สุดคือใช้ Process.Start ("7z.exe ...... )
klm_

25

นี่คือตัวอย่างการทำงานที่สมบูรณ์โดยใช้ SevenZip SDK ใน C #

มันจะเขียนและอ่านไฟล์ 7zip มาตรฐานที่สร้างโดยแอปพลิเคชัน Windows 7zip

ปล. ตัวอย่างก่อนหน้านี้ไม่เคยคลายการบีบอัดเนื่องจากไม่เคยเขียนข้อมูลคุณสมบัติที่ต้องการไปยังจุดเริ่มต้นของไฟล์

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SevenZip.Compression.LZMA;
using System.IO;
using SevenZip;

namespace VHD_Director
{
    class My7Zip
    {
        public static void CompressFileLZMA(string inFile, string outFile)
        {
            Int32 dictionary = 1 << 23;
            Int32 posStateBits = 2;
            Int32 litContextBits = 3; // for normal files
            // UInt32 litContextBits = 0; // for 32-bit data
            Int32 litPosBits = 0;
            // UInt32 litPosBits = 2; // for 32-bit data
            Int32 algorithm = 2;
            Int32 numFastBytes = 128;

            string mf = "bt4";
            bool eos = true;
            bool stdInMode = false;


            CoderPropID[] propIDs =  {
                CoderPropID.DictionarySize,
                CoderPropID.PosStateBits,
                CoderPropID.LitContextBits,
                CoderPropID.LitPosBits,
                CoderPropID.Algorithm,
                CoderPropID.NumFastBytes,
                CoderPropID.MatchFinder,
                CoderPropID.EndMarker
            };

            object[] properties = {
                (Int32)(dictionary),
                (Int32)(posStateBits),
                (Int32)(litContextBits),
                (Int32)(litPosBits),
                (Int32)(algorithm),
                (Int32)(numFastBytes),
                mf,
                eos
            };

            using (FileStream inStream = new FileStream(inFile, FileMode.Open))
            {
                using (FileStream outStream = new FileStream(outFile, FileMode.Create))
                {
                    SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
                    encoder.SetCoderProperties(propIDs, properties);
                    encoder.WriteCoderProperties(outStream);
                    Int64 fileSize;
                    if (eos || stdInMode)
                        fileSize = -1;
                    else
                        fileSize = inStream.Length;
                    for (int i = 0; i < 8; i++)
                        outStream.WriteByte((Byte)(fileSize >> (8 * i)));
                    encoder.Code(inStream, outStream, -1, -1, null);
                }
            }

        }

        public static void DecompressFileLZMA(string inFile, string outFile)
        {
            using (FileStream input = new FileStream(inFile, FileMode.Open))
            {
                using (FileStream output = new FileStream(outFile, FileMode.Create))
                {
                    SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();

                    byte[] properties = new byte[5];
                    if (input.Read(properties, 0, 5) != 5)
                        throw (new Exception("input .lzma is too short"));
                    decoder.SetDecoderProperties(properties);

                    long outSize = 0;
                    for (int i = 0; i < 8; i++)
                    {
                        int v = input.ReadByte();
                        if (v < 0)
                            throw (new Exception("Can't Read 1"));
                        outSize |= ((long)(byte)v) << (8 * i);
                    }
                    long compressedSize = input.Length - input.Position;

                    decoder.Code(input, output, compressedSize, outSize, null);
                }
            }
        }

        public static void Test()
        {
            CompressFileLZMA("DiscUtils.pdb", "DiscUtils.pdb.7z");
            DecompressFileLZMA("DiscUtils.pdb.7z", "DiscUtils.pdb2");
        }
    }
}

15
โปรดทราบว่านี่เป็นการบีบอัด / คลายการบีบอัด LZMA ล้วนๆ รูปแบบไฟล์ 7zip เป็นเลเยอร์ที่อยู่เหนือสิ่งนี้ซึ่งอนุญาตให้บรรจุไฟล์หลายไฟล์พร้อมกับชื่อไฟล์ / เส้นทางและข้อมูลเมตาของไฟล์อื่น ๆ
redcalx

1
@redcalx ถูกต้อง ใครมีเบาะแสวิธีการประมวลผลเลเยอร์ 7zip บน? การอ้างอิงถึงโพสต์ SO อื่นจะดีมาก :)
Christopher J Smith

8

ฉันใช้ sdk

เช่น:

using SevenZip.Compression.LZMA;
private static void CompressFileLZMA(string inFile, string outFile)
{
   SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();

   using (FileStream input = new FileStream(inFile, FileMode.Open))
   {
      using (FileStream output = new FileStream(outFile, FileMode.Create))
      {
          coder.Code(input, output, -1, -1, null);
          output.Flush();
      }
   }
}

7
แล้วคุณจะคลายไฟล์ได้อย่างไร? ฉันพยายามทำเช่นเดียวกันโดยใช้ SevenZip.Compression.LZMA.Decoder และเรียกด้วยรหัส (stream1, stream2, -1, -1, null); นั่นทำให้มีข้อยกเว้นข้อมูลจากกรอบ
Karsten

3
 string zipfile = @"E:\Folderx\NPPES.zip";
 string folder = @"E:\TargetFolderx";

 ExtractFile(zipfile,folder);
public void ExtractFile(string source, string destination)
        {
            // If the directory doesn't exist, create it.
            if (!Directory.Exists(destination))
                Directory.CreateDirectory(destination);

            //string zPath = ConfigurationManager.AppSettings["FileExtactorEXE"];
          //  string zPath = Properties.Settings.Default.FileExtactorEXE; ;

            string zPath=@"C:\Program Files\7-Zip\7zG.exe";

            try
            {
                ProcessStartInfo pro = new ProcessStartInfo();
                pro.WindowStyle = ProcessWindowStyle.Hidden;
                pro.FileName = zPath;
                pro.Arguments = "x \"" + source + "\" -o" + destination;
                Process x = Process.Start(pro);
                x.WaitForExit();
            }
            catch (System.Exception Ex) { }
        }

เพียงติดตั้ง 7 zip จากซอร์สและส่งพารามิเตอร์ไปยังเมธอด

ขอบคุณ. กรุณาชอบคำตอบ


สิ่งนี้ใช้ได้ผลสำหรับฉันในบริการ windows ด้วย 7za.exe
Marco Duindam

1

ฉันใช้รหัสนี้

                string PZipPath = @"C:\Program Files\7-Zip\7z.exe";
                string sourceCompressDir = @"C:\Test";
                string targetCompressName = @"C:\Test\abc.zip";
                string CompressName = targetCompressName.Split('\\').Last();
                string[] fileCompressList = Directory.GetFiles(sourceCompressDir, "*.*");

                    if (fileCompressList.Length == 0)
                    {
                        MessageBox.Show("No file in directory", "Important Message");
                        return;
                    }
                    string filetozip = null;
                    foreach (string filename in fileCompressList)
                    {
                        filetozip = filetozip + "\"" + filename + " ";
                    }

                    ProcessStartInfo pCompress = new ProcessStartInfo();
                    pCompress.FileName = PZipPath;
                    if (chkRequestPWD.Checked == true)
                    {
                        pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" " + filetozip + " -mx=9" + " -p" + tbPassword.Text;
                    }
                    else
                    {
                        pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" \"" + filetozip + "\" -mx=9";
                    }
                    pCompress.WindowStyle = ProcessWindowStyle.Hidden;
                    Process x = Process.Start(pCompress);
                    x.WaitForExit();

1

ติดตั้งแพ็คเกจ NuGet ที่เรียกว่า SevenZipSharp.Interop

จากนั้น:

SevenZipBase.SetLibraryPath(@".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(@"D:\data\");
compressor.CompressFiles(@"C:\archive\abc.7z", filesToCompress);

ฉันพยายามเพิ่มไฟล์ลงในไฟล์เก็บถาวร 7z ที่มีอยู่และได้รับไฟล์เก็บถาวรที่เสียหาย
ภูมิศาสตร์

1

ข้อมูลการทดสอบเพิ่มเติมบางอย่างเกี่ยวกับรหัส @Orwellophile โดยใช้ไฟล์ข้อความ 17.9MB
โดยใช้ค่าอสังหาริมทรัพย์ในรหัสตัวอย่างเช่น "จะเป็น" จะมีผลกระทบอย่างมากต่อประสิทธิภาพการทำงานก็จะใช้เวลา14.16 วินาที

การตั้งค่าคุณสมบัติเป็นสิ่งต่อไปนี้จะทำงานเดียวกันที่3.91 วินาที (นั่นคือไฟล์เก็บถาวรจะมีข้อมูลคอนเทนเนอร์เดียวกันนั่นคือคุณสามารถแตกและทดสอบไฟล์เก็บถาวรด้วย 7zip แต่ไม่มีข้อมูลชื่อไฟล์)

Native 7zip 2 วินาที

CoderPropID[] propIDs =  {
  //CoderPropID.DictionarySize,
  //CoderPropID.PosStateBits,
  //CoderPropID.LitContextBits,
  //CoderPropID.LitPosBits,
  //CoderPropID.Algorithm,
  //CoderPropID.NumFastBytes,
  //CoderPropID.MatchFinder,
  CoderPropID.EndMarker
};
object[] properties = {
  //(Int32)(dictionary),
  //(Int32)(posStateBits),
  //(Int32)(litContextBits),
  //(Int32)(litPosBits),
  //(Int32)(algorithm),
  //(Int32)(numFastBytes),
  //mf,
  eos
};

ฉันทำการทดสอบอีกครั้งโดยใช้ 7zip ดั้งเดิมและไฟล์สำรองข้อมูล 1,2GB SQL (.bak)
7zip (การบีบอัดสูงสุด): LZMA SDK 1 นาที
(@Orwellophile พร้อมการตั้งค่าคุณสมบัติด้านบน): 12:26 นาที :-(
ไฟล์เอาต์พุตขนาดประมาณเดียวกัน .

ดังนั้นฉันเดาว่าฉันจะใช้วิธีแก้ปัญหาที่อิงตามเครื่องยนต์ c / c ++ ia เรียกใช้งาน 7zip จาก c # หรือใช้Squid-box / SevenZipSharpซึ่งเป็นกระดาษห่อหุ้มรอบไฟล์ 7zip c / c ++ dll และดูเหมือนว่า เป็นทางแยกใหม่ล่าสุดของ SevenZipSharp ยังไม่ได้ทดสอบกระดาษห่อหุ้ม แต่ฉันหวังว่าจะทำงานได้เหมือนกับ 7zip ดั้งเดิม แต่หวังว่ามันจะให้ความเป็นไปได้ในการบีบอัดสตรีมซึ่งคุณไม่สามารถทำได้หากคุณโทรหา exe โดยตรง มิฉะนั้นฉันเดาว่าไม่มีประโยชน์มากกว่าการโทรหา exe Wrapper มีการอ้างอิงเพิ่มเติมดังนั้นจะไม่ทำให้โครงการที่เผยแพร่ของคุณ "สะอาดขึ้น"

ดูเหมือนว่าทีมงาน. Net Core จะพิจารณาใช้ LZMA ในคลาส system.io ใน. Core ver. 5 นั่นจะดีมาก!

(ฉันรู้ว่านี่เป็นความคิดเห็นไม่ใช่คำตอบ แต่เพื่อให้สามารถให้ข้อมูลโค้ดได้จึงไม่สามารถแสดงความคิดเห็นได้)


0

วิธีที่ง่ายที่สุดคือใช้ไฟล์. zip แทน. 7z และใช้Dot Net Zip

เมื่อหมุนคำสั่ง 7zip ไปยังเชลล์มีปัญหาอื่น ๆ เช่นสิทธิ์ของผู้ใช้ฉันมีปัญหากับ SevenZipSharp

Private Function CompressFile(filename As String) As Boolean
Using zip As New ZipFile()
    zip.AddFile(filename & ".txt", "")
    zip.Save(filename & ".zip")
End Using

Return File.Exists(filename & ".zip")
End Function

0

SharpCompressเป็นหนึ่งในไลบรารีการบีบอัดที่ฉลาดที่สุดในโลก รองรับ LZMA (7-zip) ใช้งานง่ายและอยู่ระหว่างการพัฒนา

เนื่องจากมีการสนับสนุนการสตรีม LZMA อยู่แล้วในขณะที่เขียนจึงรองรับการอ่านไฟล์เก็บถาวรแบบ 7 ซิปเท่านั้น แต่การเขียนที่เก็บถาวรอยู่ในรายการสิ่งที่ต้องทำ (ดู readme) สำหรับผู้อ่านในอนาคต: ตรวจสอบเพื่อรับสถานะปัจจุบันที่นี่: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.