как мне заархивировать файл в c #, не используя сторонние api?

<p>я уверен, что это не дубликат, так что потерпите меня на минуту.</p><p>как я могу программно (c #) архивировать файл (в windows) без использования сторонних библиотек? мне нужен родной вызов windows или что-то в этом роде; мне действительно не нравится идея начать процесс, но я буду любить, если мне будет абсолютно необходимо. а на пиновке был бы звонок намного лучше.</p><p>если это не удастся, позвольте мне рассказать вам, чего я на самом деле пытаюсь достичь: мне нужна возможность позволить пользователю загружать коллекцию документов за один запрос. есть идеи, как этого добиться?</p>

<p>вы используете .net 3.5? вы можете использовать класс <a href="http://msdn.microsoft.com/en-us/library/system.io.packaging.zippackage%28v=vs.90%29.aspx"><code>zippackage</code></a> и связанные с ним классы. это больше, чем просто архивирование списка файлов, потому что ему нужен тип mime для каждого добавляемого вами файла. это может делать то, что вы хотите.</p><p>в настоящее время я использую эти классы для аналогичной проблемы, чтобы заархивировать несколько связанных файлов в один файл для загрузки. мы используем расширение файла, чтобы связать загружаемый файл с нашим настольным приложением. одна небольшая проблема, с которой мы столкнулись, заключалась в том, что для создания zip-файлов просто невозможно использовать сторонний инструмент, такой как 7-zip, поскольку клиентский код не может его открыть - zippackage добавляет скрытый файл, описывающий тип содержимого каждый файл компонента и не может открыть файл zip, если файл этого типа содержимого отсутствует.</p>

<blockquote> <p>как я могу программно (c #) zip файл (в windows) без использования какие-нибудь сторонние библиотеки?</p> </blockquote><p>если используется 4.5+ framework, теперь есть классы <a href="http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive%28v=vs.110%29.aspx">ziparchive</a> и <a href="http://msdn.microsoft.com/en-us/library/system.io.compression.zipfile%28v=vs.110%29.aspx">zipfile</a> .</p><pre><code>using (ziparchive zip = zipfile.open("test.zip", ziparchivemode.create)) { zip.createentryfromfile(@"c:\something.txt", "data/path/something.txt"); } </code></pre><p>вам необходимо добавить ссылки на:</p><ul> <li><strong>system.io.compression</strong></li> <li><strong>system.io.compression.filesystem</strong></li> </ul><p>для .net core с таргетингом на net46 необходимо добавить зависимости для </p><ul> <li><strong>system.io.compression</strong> </li> <li><strong>system.io.compression.zipfile</strong></li> </ul><p>пример project.json:</p><pre><code>"dependencies": { "system.io.compression": "4.1.0", "system.io.compression.zipfile": "4.0.1" }, "frameworks": { "net46": {} } </code></pre><p>для .net core 2.0 достаточно просто добавить простую инструкцию использования:</p><ul> <li><strong>использование system.io.compression;</strong></li> </ul>

<p>я был в той же ситуации, желая .net вместо сторонней библиотеки. как уже упоминалось выше, просто использовать класс zippackage (представленный в .net 3.5) недостаточно. для работы zippackage существует дополнительный файл, который должен быть включен в архив. если этот файл добавлен, то полученный пакет zip можно открыть непосредственно из windows explorer - без проблем.</p><p>все, что вам нужно сделать, это добавить файл [content\_types] .xml в корень архива с узлом «по умолчанию» для каждого расширения файла, которое вы хотите включить. после добавления я мог просматривать пакет из windows explorer или программно распаковывать и читать его содержимое.</p><p>дополнительную информацию о файле [content\_types] .xml можно найти здесь: <a href="http://msdn.microsoft.com/en-us/magazine/cc163372.aspx">http://msdn.microsoft.com/en-us/magazine/cc163372.aspx</a> </p><p>вот пример файла [content\_types] .xml (должен иметь точное имя):</p><pre><code><?xml version="1.0" encoding="utf-8" ?> <types xmlns= "http://schemas.openxmlformats.org/package/2006/content-types"> <default extension="xml" contenttype="text/xml" /> <default extension="htm" contenttype="text/html" /> <default extension="html" contenttype="text/html" /> <default extension="rels" contenttype= "application/vnd.openxmlformats-package.relationships+xml" /> <default extension="jpg" contenttype="image/jpeg" /> <default extension="png" contenttype="image/png" /> <default extension="css" contenttype="text/css" /> </types> </code></pre><p>и c # для создания zip-файла:</p><pre><code>var zipfilepath = "c:\\myfile.zip"; var tempfolderpath = "c:\\unzipped"; using (package package = zippackage.open(zipfilepath, filemode.open, fileaccess.read)) { foreach (packagepart part in package.getparts()) { var target = path.getfullpath(path.combine(tempfolderpath, part.uri.originalstring.trimstart('/'))); var targetdir = target.remove(target.lastindexof('\\')); if (!directory.exists(targetdir)) directory.createdirectory(targetdir); using (stream source = part.getstream(filemode.open, fileaccess.read)) { source.copyto(file.openwrite(target)); } } } </code></pre><p>замечания: </p><ul> <li>этот код использует метод stream.copyto в .net 4.0</li> <li>это станет намного проще с введением класса ziparchive в .net 4.5: <a href="http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx">http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110). aspx</a> </li> </ul>

<pre><code> private static string compressfile(string sourcefilename) { using (ziparchive archive = zipfile.open(path.changeextension(sourcefilename, ".zip"), ziparchivemode.create)) { archive.createentryfromfile(sourcefilename, path.getfilename(sourcefilename)); } return path.changeextension(sourcefilename, ".zip"); } </code></pre>

<p>для приложения .net 2.0 я использовал <a href="http://www.icsharpcode.net/opensource/sharpziplib/">sharpziplib</a> . простой в использовании и с открытым исходным кодом. </p>

<p>исходя из ответа саймона маккензи <a href="https://stackoverflow.com/questions/1023476/recommend-a-library-api-to-unzip-file-in-c-sharp?rq=1">на этот вопрос</a> , я бы предложил использовать пару таких методов:</p><pre><code> public static void zipfolder(string sourcefolder, string zipfile) { if (!system.io.directory.exists(sourcefolder)) throw new argumentexception("sourcedirectory"); byte[] zipheader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; using (system.io.filestream fs = system.io.file.create(zipfile)) { fs.write(zipheader, 0, zipheader.length); } dynamic shellapplication = activator.createinstance(type.gettypefromprogid("shell.application")); dynamic source = shellapplication.namespace(sourcefolder); dynamic destination = shellapplication.namespace(zipfile); destination.copyhere(source.items(), 20); } public static void unzipfile(string zipfile, string targetfolder) { if (!system.io.directory.exists(targetfolder)) system.io.directory.createdirectory(targetfolder); dynamic shellapplication = activator.createinstance(type.gettypefromprogid("shell.application")); dynamic compressedfoldercontents = shellapplication.namespace(zipfile).items; dynamic destinationfolder = shellapplication.namespace(targetfolder); destinationfolder.copyhere(compressedfoldercontents); } } </code></pre>

<p>похоже, windows может просто позволить вам сделать <a href="http://www.codeproject.com/kb/cs/decompresswinshellapics.aspx?df=100&forumid=221403&exp=0&select=1253354">это</a> ...</p><p>к сожалению, я не думаю, что вы сможете начать отдельный процесс, если не перейдете к стороннему компоненту. </p>

<p>добавьте эти 4 функции в ваш проект:</p><pre><code> public const long buffer\_size = 4096; public static void addfiletozip(string zipfilename, string filetoadd) { using (package zip = global::system.io.packaging.package.open(zipfilename, filemode.openorcreate)) { string destfilename = ".\\" + path.getfilename(filetoadd); uri uri = packurihelper.createparturi(new uri(destfilename, urikind.relative)); if (zip.partexists(uri)) { zip.deletepart(uri); } packagepart part = zip.createpart(uri, "", compressionoption.normal); using (filestream filestream = new filestream(filetoadd, filemode.open, fileaccess.read)) { using (stream dest = part.getstream()) { copystream(filestream, dest); } } } } public static void copystream(global::system.io.filestream inputstream, global::system.io.stream outputstream) { long buffersize = inputstream.length < buffer\_size ? inputstream.length : buffer\_size; byte[] buffer = new byte[buffersize]; int bytesread = 0; long byteswritten = 0; while ((bytesread = inputstream.read(buffer, 0, buffer.length)) != 0) { outputstream.write(buffer, 0, bytesread); byteswritten += bytesread; } } public static void removefilefromzip(string zipfilename, string filetoremove) { using (package zip = global::system.io.packaging.package.open(zipfilename, filemode.openorcreate)) { string destfilename = ".\\" + filetoremove; uri uri = packurihelper.createparturi(new uri(destfilename, urikind.relative)); if (zip.partexists(uri)) { zip.deletepart(uri); } } } public static void remove\_content\_types\_fromzip(string zipfilename) { string contents; using (zipfile zipfile = new zipfile(file.open(zipfilename, filemode.open))) { /* zipentry startpartentry = zipfile.getentry("[content\_types].xml"); using (streamreader reader = new streamreader(zipfile.getinputstream(startpartentry))) { contents = reader.readtoend(); } xelement contenttypes = xelement.parse(contents); xnamespace xs = contenttypes.getdefaultnamespace(); xelement newdefext = new xelement(xs + "default", new xattribute("extension", "sab"), new xattribute("contenttype", @"application/binary; modeler=acis; version=18.0.2application/binary; modeler=acis; version=18.0.2")); contenttypes.add(newdefext); contenttypes.save("[content\_types].xml"); zipfile.beginupdate(); zipfile.add("[content\_types].xml"); zipfile.commitupdate(); file.delete("[content\_types].xml"); */ zipfile.beginupdate(); try { zipfile.delete("[content\_types].xml"); zipfile.commitupdate(); } catch{} } } </code></pre><p>и используйте их так:</p><pre><code>foreach (string f in unitziplist) { addfiletozip(zipfile, f); system.io.file.delete(f); } remove\_content\_types\_fromzip(zipfile); </code></pre>