เปิดเครื่องรูดไฟล์โดยทางโปรแกรมใน. net


221

ฉันพยายามที่จะคลายซิปไฟล์โดยทางโปรแกรม

ฉันได้ลองใช้System.IO.Compression.GZipStreamคลาสใน. NET แต่เมื่อแอพของฉันทำงาน (จริง ๆ แล้วเป็นการทดสอบหน่วย) ฉันได้รับข้อยกเว้นนี้:

System.IO.InvalidDataException: หมายเลขเวทย์มนตร์ในส่วนหัว GZip ไม่ถูกต้อง ตรวจสอบให้แน่ใจว่าคุณกำลังผ่านกระแส GZip ..

ตอนนี้ผมตระหนักดีว่า.zipไฟล์ไม่เช่นเดียวกับ.gzไฟล์และที่ไม่ได้เป็นเช่นเดียวกับGZipZip

อย่างไรก็ตามเนื่องจากฉันสามารถแตกไฟล์ด้วยตนเองโดยดับเบิลคลิกที่ไฟล์ซิปแล้วคลิกปุ่ม "แตกไฟล์ทั้งหมด" - ปุ่มฉันคิดว่าควรมีวิธีการทำเช่นนั้นในรหัสเช่นกัน

ดังนั้นฉันจึงพยายามใช้Process.Start()กับพา ธ ไปยังไฟล์ซิปเป็นอินพุต นี่ทำให้แอปของฉันเปิดหน้าต่างที่แสดงเนื้อหาในไฟล์ซิป ไม่เป็นไร แต่แอปจะถูกติดตั้งบนเซิร์ฟเวอร์โดยไม่มีปุ่มคลิก "แตกไฟล์ทั้งหมด" -

ดังนั้นฉันจะทำให้แอพของฉันแตกไฟล์ในไฟล์ซิปได้อย่างไร

หรือมีวิธีอื่นที่จะทำหรือไม่ ฉันชอบที่จะทำมันด้วยโค้ดโดยไม่ต้องดาวน์โหลดไลบรารีหรือแอพของบุคคลที่สามใด ๆ แผนกรักษาความปลอดภัยไม่แฟนซีเกินไปเกี่ยวกับเรื่องนั้น ...


12
แผนกความปลอดภัยของคุณมีความสุขกับการที่คุณเขียนโค้ดของคุณเองสำหรับบางอย่างมากกว่าการใช้ห้องสมุดที่ดีบั๊กและมองด้วยสายตาหลาย ๆ คน? คุณสามารถใช้ห้องสมุดและ "ทำมันในรหัส" (รับแหล่งที่มาและรวบรวมมันด้วยตัวเอง) แต่ฉันเห็น reinventing ล้อเป็นปัญหาใหญ่กว่าปัญหาด้านความปลอดภัยใด ๆ ที่เกิดขึ้นโดยใช้ห้องสมุดลองและจริง
Jared Updike

10
@Jared - เมื่อได้รับการจัดการความคิดในหัวของพวกเขา ...
สตีเว่น Evers

4
แผนกความปลอดภัยมีความเสี่ยงน้อยกว่าหากคุณได้รับผลิตภัณฑ์จากบุคคลที่สาม เพียงดาวน์โหลด DotNetZip และเปลี่ยนชื่อมันว่า "[ใส่ชื่อ บริษัท ] .ziplibrary.dll"
ไซมอน

คำตอบ:


59

เราใช้SharpZipLibสำเร็จในหลาย ๆ โครงการ ฉันรู้ว่ามันเป็นเครื่องมือของบุคคลที่สาม แต่มีซอร์สโค้ดรวมอยู่และสามารถให้ข้อมูลเชิงลึกบางอย่างหากคุณเลือกที่จะบูรณาการล้อที่นี่


3
ฉันลองใช้ SharpZipLib และใช้งานได้ดี ฉันเดาว่าฉันต้องดูว่าการห้าม libs และ apss ของบุคคลที่สามนั้นเป็นกฎที่เข้มงวดหรือมากกว่านั้นเป็นแนวทาง
Petteri

10
ฉันไม่รู้เกี่ยวกับ บริษัท ของคุณ แต่ประสบการณ์ของฉันมักจะเป็นไปได้ที่จะได้รับข้อยกเว้นของกฎประเภทนั้นถ้าคุณเขียนคำอธิบายกรณีศึกษาทางธุรกิจว่าทำไมคุณถึงต้องการข้อยกเว้น ชี้ให้เห็นถึงการประหยัดต้นทุน v. DIY เช่นเดียวกับความจริงที่ว่าสามารถตรวจสอบแหล่งที่มาได้ ในฐานะทางเลือกคุณมักจะได้รับอนุญาตให้ใช้แหล่งข้อมูลแม้ว่าจะไม่อนุญาตให้คุณใช้ dll - จากนั้นก็รวบรวมมันเอง (หรืออย่างน้อยก็ส่วนที่คุณต้องใช้ ... )
RolandTumble

คุณไม่ต้องใช้ไลบรารีภายนอกเพื่อคลายการบีบอัดไฟล์ zip คุณสามารถใช้ Shell32 จาก System32 โปรดดูstackoverflow.com/a/43066281/948694
arturn

490

ด้วย. NET 4.5คุณสามารถคลายซิปไฟล์โดยใช้. NET Framework:

using System;
using System.IO;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string startPath = @"c:\example\start";
      string zipPath = @"c:\example\result.zip";
      string extractPath = @"c:\example\extract";

      System.IO.Compression.ZipFile.CreateFromDirectory(startPath, zipPath);
      System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
  }
}

รหัสข้างต้นถูกนำมาโดยตรงจากเอกสารของ Microsoft: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFileSystem.IO.Compression.FileSystemที่มีอยู่ในการชุมนุม (ขอบคุณ nateirvin ... ดูความคิดเห็นด้านล่าง)


118
BTW, ที่มีอยู่ในการชุมนุมZipFile System.IO.Compression.FileSystem
nateirvin

73
ซึ่งหมายความว่าคุณต้องเพิ่มการอ้างอิง DLL ไปยังแอสเซมบลีเฟรมเวิร์System.IO.Compression.FileSystem.dll
Chris Schiffhauer

เกี่ยวกับไฟล์. rar โค้ดด้านบนไม่สามารถแยกไฟล์. rar
Raghu

1
ฉันพยายามนี้ในเว็บ API asp.net หลักของฉันก็อ่านดีรายการแรก A local file header is corruptแต่ในรายการที่สองก็มักจะให้ข้อผิดพลาด มีอะไรบ้างในเรื่องนี้?
SoftSan

เช่นเดียวกันกับ @SoftSan ฉันยังได้รับข้อผิดพลาดนั้น จะทำอย่างไร?
รวย

101

สำหรับ. Net 4.5+

ไม่ต้องการเขียนไฟล์ที่ไม่มีการบีบอัดลงดิสก์เสมอไป ในฐานะนักพัฒนา ASP.Net ฉันจะต้องเล่นซอกับสิทธิ์อนุญาตให้แอปพลิเคชันของฉันเขียนไปยังระบบไฟล์ ด้วยการทำงานร่วมกับสตรีมในหน่วยความจำฉันสามารถก้าวเท้าเลี่ยงสิ่งนั้นและอ่านไฟล์ได้โดยตรง:

using (ZipArchive archive = new ZipArchive(postedZipStream))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
         var stream = entry.Open();
         //Do awesome stream stuff!!
    }
}

อีกทางหนึ่งคุณยังสามารถเขียนไฟล์ที่คลายการบีบอัดไว้ในดิสก์ได้โดยการโทรExtractToFile():

using (ZipArchive archive = ZipFile.OpenRead(pathToZip))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine(destination, entry.FullName));
    }
} 

เมื่อต้องการใช้ZipArchiveระดับคุณจะต้องเพิ่มการอ้างอิงถึงSystem.IO.Compressionnamespace System.IO.Compression.FileSystemและ


8
ใช้ MSFT จนถึง 4.5+ เพื่อเพิ่มตัวขยายการบีบอัดดั้งเดิมหรือไม่
John Peters

2
@JohnPeters GZipStream ถูกเพิ่มกลับมาใน. Net 2.0 ( msdn.microsoft.com/en-us/library/… ) อย่างไรก็ตามมันไม่ได้ทำให้ง่ายต่อการทำงานกับหลาย ๆ ไฟล์ในไฟล์เก็บถาวรในหน่วยความจำ ZipArchiveวัตถุใหม่ที่เหมาะกับการเรียกเก็บเงินอย่างดี
นายมหากาพย์

1
นี่เป็นทางเลือกที่ดีโดยเฉพาะอย่างยิ่งเพราะช่วยให้สามารถขยายไฟล์โดยไม่ต้องใช้ระบบไฟล์ (ในกรณีของฉันฉันทำงานกับทรัพยากรฝังตัว) และยังไม่ใช่ส่วนขยายของบุคคลที่สาม
Aneves

1
ทำไมฉันจึงควรใช้การforeachวนซ้ำExtractToFileเมื่อฉันสามารถใช้ZipFile.ExtractToDirectory(inputFile, outputDir);ข้อดีของวิธีแรกคืออะไร
หุ่นยนต์ปุย

1
ใน. NET 4.6.1 ฉันไม่สามารถรับ 'ZipArchive' จาก 'System.IO.Compression.FileSystem' ความคิดใด ๆ
ราวีอานันท์

55

ฟรีและไม่มีไฟล์ DLL ภายนอก ทุกอย่างอยู่ในไฟล์ CS เดียว การดาวน์โหลดเพียงไฟล์เดียวเป็นไฟล์ CS อีกดาวน์โหลดเป็นตัวอย่างที่เข้าใจง่าย เพิ่งลองวันนี้และฉันไม่อยากจะเชื่อเลยว่าการตั้งค่านั้นง่ายเพียงใด มันใช้งานได้ในการลองครั้งแรกไม่มีข้อผิดพลาดไม่มีอะไร

https://github.com/jaime-olivares/zipstorer


พูดเร็วเกินไป! ฉันต้องการขยายไฟล์จากสตรีมการดาวน์โหลด http ทันที ไม่ทำงานเนื่องจากใช้การดำเนินการ Seek ในสตรีม :( ขอบคุณซอร์สโค้ดฉันสามารถเขียน ZipStream ของตัวเองตอนนี้ ...
oyophant

ทางออกที่ดีที่สุดในการแก้ไขปัญหาของฉันตั้งแต่ฉันเขียนแอป updater และฉันไม่สามารถเกี่ยวข้องกับ DLLs ใด ๆ ในกระบวนการแยกตั้งแต่นั้นฉันจะต้องอัปเดตเหล่านั้นด้วย .... นี่เป็นสิ่งที่ดีขอขอบคุณ!
Niklas

27

ใช้ไลบรารี DotNetZip ที่http://www.codeplex.com/DotNetZip

ไลบรารีคลาสและชุดเครื่องมือสำหรับจัดการไฟล์ซิป ใช้ VB, C # หรือภาษา. NET เพื่อสร้างแยกหรืออัปเดตไฟล์ zip อย่างง่ายดาย ...

DotNetZip ทำงานบนพีซีที่มี. NET Framework แบบเต็มและยังทำงานบนอุปกรณ์พกพาที่ใช้. NET Compact Framework สร้างและอ่านไฟล์ zip ใน VB, C # หรือภาษา. NET หรือสภาพแวดล้อมการเขียนสคริปต์ใด ๆ ...

หากสิ่งที่คุณต้องการคือคลาส DeflateStream หรือ GZipStream ที่ดีกว่าเพื่อแทนที่คลาสที่มีอยู่ใน. NET BCL นั้น DotNetZip ก็มีเช่นกัน DeflateStream และ GZipStream ของ DotNetZip มีอยู่ในแอสเซมบลีแบบสแตนด์อโลนโดยอ้างอิงจาก. NET พอร์ต Zlib สตรีมเหล่านี้รองรับระดับการบีบอัดและมอบประสิทธิภาพที่ดีกว่าคลาสในตัว นอกจากนี้ยังมี ZlibStream เพื่อให้การตั้งค่าเสร็จสมบูรณ์ (RFC 1950, 1951, 1952) ...


1
อืม ... แต่นั่นเป็นห้องสมุดบุคคลที่สาม!
Petteri

30
ช่างสังเกตคุณมากแค่ไหน หากคุณไม่ต้องการใช้เวลาหลายเดือนในการทำให้ตัวอ่านไฟล์ Zip ของคุณเป็นตัวเลือกที่ดีที่สุด
Sam Axe

อันนี้ดีกว่า SharpZipLib
Kugel

5
คุณกำลังถามคำถามเกี่ยวกับคำตอบที่อายุเกือบ 5 ปี ทำวิจัยบางอย่าง. ฉันแน่ใจว่าคุณจะพบคำตอบ
Sam Axe

2
@PhilCooper นี่เป็นคำถามที่เก่ามากที่ฉันแนะนำให้ใช้ในตัว System.IO.Compression.ZipFile IIRC ฉันเคยมีประสบการณ์ที่ไม่ดีกับ SharpZipLib ในอดีตจากประสบการณ์ของฉันในการผลิต zips นับพันทันที
Kugel

9
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

ในการใช้คลาส ZipFile คุณต้องเพิ่มการอ้างอิงไปยังแอสเซมบลี System.IO.Compression.FileSystem ในโครงการของคุณ



2

ไฟล์ zip มาตรฐานจะใช้อัลกอริทึมแบบยุบ

ในการแยกไฟล์โดยไม่ใช้ไลบรารี่ของบุคคลที่สามให้ใช้ DeflateStream คุณจะต้องมีข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบการจัดเก็บไฟล์ซิปเนื่องจาก Microsoft ให้อัลกอริทึมการบีบอัด

คุณอาจลองใช้ zipfldr.dll เป็นไลบรารีการบีบอัดของ Microsoft (โฟลเดอร์ที่บีบอัดจากเมนู Send to) ดูเหมือนว่าจะเป็นห้องสมุด com แต่ไม่มีเอกสาร คุณอาจสามารถทำให้มันผ่านการทดลองได้


ฉันลองคลาส DeflateStream เวลานี้ผมได้รับ System.IO.InvalidDataException: บล็อกความยาวไม่ตรงกับที่มีส่วนประกอบของมัน ..
Petteri

ดังที่ฉันได้กล่าวไว้ข้างต้น Microsoft ให้อัลกอริทึมเท่านั้น คุณจะต้องการข้อมูลเกี่ยวกับรูปแบบไฟล์ zip เช่นกัน en.wikipedia.org/wiki/ZIP_(file_format)คุณควรเริ่มต้น ดูการอ้างอิงที่ด้านล่างของหน้าสำหรับลิงค์ไปยังข้อมูลรายละเอียดเพิ่มเติม
Kenneth Cochran

2
ฉันก็เจอ System.IO.Packaging.Package ในแพคเกจ. NET 3.5 ดูเหมือนว่ามันอาจทำการหลอกลวงได้ แต่มันก็ไม่ง่ายนัก
Kenneth Cochran

2

ฉันใช้สิ่งนี้เพื่อ zip หรือ unzip หลายไฟล์ ไม่จำเป็นต้องใช้ Regex แต่ฉันใช้เพื่อเปลี่ยนการประทับวันที่และลบเครื่องหมายขีดล่างที่ไม่ต้องการ ฉันใช้สตริงว่างในสตริงการบีบอัด >> zipPath เพื่อนำหน้าบางสิ่งไปยังไฟล์ทั้งหมดหากจำเป็น นอกจากนี้ฉันมักจะแสดงความคิดเห็นทั้ง Compress () หรือ Decompress () ตามสิ่งที่ฉันทำ

using System;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;

namespace ZipAndUnzip
{
    class Program
    {
        static void Main(string[] args)
        {
            var directoryPath = new DirectoryInfo(@"C:\your_path\");

            Compress(directoryPath);
            Decompress(directoryPath);
        }

        public static void Compress(DirectoryInfo directoryPath)
        {
            foreach (DirectoryInfo directory in directoryPath.GetDirectories())
            {
                var path = directoryPath.FullName;
                var newArchiveName = Regex.Replace(directory.Name, "[0-9]{8}", "20130913");
                newArchiveName = Regex.Replace(newArchiveName, "[_]+", "_");
                string startPath = path + directory.Name;
                string zipPath = path + "" + newArchiveName + ".zip";

                ZipFile.CreateFromDirectory(startPath, zipPath);
            }

        }

        public static void Decompress(DirectoryInfo directoryPath)
        {
            foreach (FileInfo file in directoryPath.GetFiles())
            {
                var path = directoryPath.FullName;
                string zipPath = path + file.Name;
                string extractPath = Regex.Replace(path + file.Name, ".zip", "");

                ZipFile.ExtractToDirectory(zipPath, extractPath);
            }
        }


    }
}

สิ่งนี้ต้องใช้ dot net 4.5 - เป็นโน้ตที่คนอื่น ๆ ที่ตอบด้วย ZipFile ตั้งข้อสังเกตและฉันยังใช้ 3.5
Thronk


1

จากที่นี่ :

วัตถุ GZipStream ที่ถูกบีบอัดที่เขียนไปยังไฟล์ที่มีนามสกุล. gz สามารถแตกได้โดยใช้เครื่องมือบีบอัดทั่วไป อย่างไรก็ตามคลาสนี้ไม่ได้จัดเตรียมฟังก์ชันการทำงานสำหรับการเพิ่มไฟล์ไปยังหรือแตกไฟล์จากไฟล์. zip แบบถาวร


1

คุณสามารถทำได้ทั้งหมดภายใน. NET 3.5 โดยใช้ DeflateStream สิ่งที่ขาดใน. NET 3.5 คือความสามารถในการประมวลผลส่วนหัวของไฟล์ที่ใช้ในการจัดระเบียบไฟล์ซิป PKWare ได้เผยแพร่ข้อมูลนี้ซึ่งคุณสามารถใช้ในการประมวลผลไฟล์ zip หลังจากที่คุณสร้างโครงสร้างที่ใช้ มันไม่ได้เป็นภาระโดยเฉพาะและมันเป็นวิธีที่ดีในการสร้างเครื่องมือโดยไม่ต้องใช้รหัสของบุคคลที่สาม

มันไม่ใช่คำตอบเดียว แต่สามารถทำได้อย่างสมบูรณ์หากคุณเต็มใจและสามารถใช้เวลาด้วยตัวเอง ฉันเขียนชั้นเรียนเพื่อทำสิ่งนี้ในสองสามชั่วโมงและสิ่งที่ฉันได้จากสิ่งนั้นคือความสามารถในการ zip และ unzip ไฟล์โดยใช้. NET 3.5 เท่านั้น


0

ฉันค้นพบเกี่ยวกับหนึ่ง (Unzip แพ็คเกจใน NuGet) วันนี้เนื่องจากฉันพบข้อบกพร่องอย่างหนักใน DotNetZip และฉันก็รู้ว่ามันไม่ได้มีงานที่ทำบน DotNetZip มากนักในช่วงสองปีที่ผ่านมา

แพ็คเกจ Unzip ไม่ติดมันและทำงานให้ฉันได้ - มันไม่มีข้อผิดพลาดที่ DotNetZip มี นอกจากนี้ยังเป็นไฟล์ที่มีขนาดเล็กพอสมควรโดยอาศัย BCL ของ Microsoft สำหรับการแตกไฟล์จริง ฉันสามารถทำการปรับเปลี่ยนได้อย่างง่ายดายตามที่ต้องการ (เพื่อให้สามารถติดตามความคืบหน้าได้ในขณะที่คลายการบีบอัด) ฉันแนะนำมัน


0

จาก Ressources แบบฝัง:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}

0

จนถึงตอนนี้ฉันใช้กระบวนการ cmd เพื่อแยกไฟล์. iso คัดลอกลงในพา ธ ชั่วคราวจากเซิร์ฟเวอร์และแยกบน usb stick เมื่อเร็ว ๆ นี้ฉันพบว่าสิ่งนี้ทำงานได้อย่างสมบูรณ์กับ. iso ที่น้อยกว่า 10Gb สำหรับ iso เช่น 29Gb วิธีการนี้จะติดอยู่อย่างใด

    public void ExtractArchive()
    {
        try
        {

            try
            {
                Directory.Delete(copyISOLocation.OutputPath, true); 
            }
            catch (Exception e) when (e is IOException || e is UnauthorizedAccessException)
            {
            }

            Process cmd = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            //stackoverflow
            cmd.StartInfo.Arguments = "-R";

            cmd.Disposed += (sender, args) => {
                Console.WriteLine("CMD Process disposed");
            };
            cmd.Exited += (sender, args) => {
                Console.WriteLine("CMD Process exited");
            };
            cmd.ErrorDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process error data received");
                Console.WriteLine(args.Data);
            };
            cmd.OutputDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process Output data received");
                Console.WriteLine(args.Data);
            };

            //stackoverflow


            cmd.Start();

            cmd.StandardInput.WriteLine("C:");
            //Console.WriteLine(cmd.StandardOutput.Read());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine("cd C:\\\"Program Files (x86)\"\\7-Zip\\");
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine(string.Format("7z.exe x -o{0} {1}", copyISOLocation.OutputPath, copyISOLocation.TempIsoPath));
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            cmd.WaitForExit();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            Console.WriteLine(cmd.StandardError.ReadToEnd());

0

คุณสามารถใช้cod - line คำสั่งInfo-unzip ได้เพียงดาวน์โหลด unzip.exe จากเว็บไซต์ทางการ Info-unzip

 internal static void Unzip(string sorcefile)
    {
        try
        {
            AFolderFiles.AFolderFilesDelete.DeleteFolder(TempBackupFolder); // delete old folder   
            AFolderFiles.AFolderFilesCreate.CreateIfNotExist(TempBackupFolder); // delete old folder   
           //need to Command command also to export attributes to a excel file
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // window type
            startInfo.FileName = UnzipExe;
            startInfo.Arguments = sorcefile + " -d " + TempBackupFolder;
            process.StartInfo = startInfo;
            process.Start();
            //string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            process.Dispose();
            process.Close();
        }
        catch (Exception ex){ throw ex; }
    }        
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.