17 using System.Collections.Generic;
18 using System.Diagnostics;
20 using System.IO.Compression;
23 using System.Threading.Tasks;
24 using ICSharpCode.SharpZipLib.Core;
25 using ICSharpCode.SharpZipLib.GZip;
26 using ICSharpCode.SharpZipLib.Tar;
29 using ZipEntry = ICSharpCode.SharpZipLib.Zip.ZipEntry;
30 using ZipFile = Ionic.Zip.ZipFile;
31 using ZipInputStream = ICSharpCode.SharpZipLib.Zip.ZipInputStream;
32 using ZipOutputStream = ICSharpCode.SharpZipLib.Zip.ZipOutputStream;
45 private static bool IsLinux
49 var p = (int)Environment.OSVersion.Platform;
50 return (p == 4) || (p == 6) || (p == 128);
60 public static bool ZipData(
string zipPath, Dictionary<string, string> filenamesAndData)
65 using (var stream =
new ZipOutputStream(File.Create(zipPath)))
68 foreach (var kvp
in filenamesAndData)
70 var filename = kvp.Key;
72 var entry =
new ZipEntry(filename);
73 var bytes = Encoding.Default.GetBytes(kvp.Value);
74 stream.PutNextEntry(entry);
75 stream.Write(bytes, 0, bytes.Length);
98 public static bool ZipData(
string zipPath, IEnumerable<KeyValuePair<
string,
byte[]>> filenamesAndData)
101 var buffer =
new byte[4096];
106 using (var stream =
new ZipOutputStream(File.Create(zipPath)))
108 foreach (var file
in filenamesAndData)
111 var entry =
new ZipEntry(file.Key);
113 stream.PutNextEntry(entry);
115 using (var ms =
new MemoryStream(file.Value))
120 sourceBytes = ms.Read(buffer, 0, buffer.Length);
121 stream.Write(buffer, 0, sourceBytes);
123 while (sourceBytes > 0);
132 catch (Exception err)
147 public static bool ZipData(
string zipPath,
string zipEntry, IEnumerable<string> lines)
151 using (var stream =
new ZipOutputStream(File.Create(zipPath)))
152 using (var writer =
new StreamWriter(stream))
154 var entry =
new ZipEntry(zipEntry);
155 stream.PutNextEntry(entry);
156 foreach (var line
in lines)
158 writer.WriteLine(line);
163 catch (Exception err)
178 public static bool ZipCreateAppendData(
string path,
string entry,
string data,
bool overrideEntry =
false)
182 using (var zip = File.Exists(path) ? ZipFile.Read(path) :
new ZipFile(path))
184 if (zip.ContainsEntry(entry) && overrideEntry)
186 zip.RemoveEntry(entry);
189 zip.AddEntry(entry, data);
190 zip.UseZip64WhenSaving = Zip64Option.Always;
194 catch (Exception err)
210 public static bool ZipCreateAppendData(
string path,
string entry,
byte[] data,
bool overrideEntry =
false)
214 using (var zip = File.Exists(path) ? ZipFile.Read(path) :
new ZipFile(path))
216 if (overrideEntry && zip.ContainsEntry(entry))
218 zip.RemoveEntry(entry);
221 zip.AddEntry(entry, data);
222 zip.UseZip64WhenSaving = Zip64Option.Always;
226 catch (Exception err)
228 Log.
Error(err, $
"file: {path} entry: {entry}");
240 public static Dictionary<string, string>
UnzipData(
byte[] zipData, Encoding encoding =
null)
242 using var stream =
new MemoryStream(zipData);
243 return UnzipDataAsync(stream, encoding).ConfigureAwait(
false).GetAwaiter().GetResult();
252 public static async Task<Dictionary<string, string>>
UnzipDataAsync(Stream stream, Encoding encoding =
null)
255 var data =
new Dictionary<string, string>();
260 using (var zipStream =
new ZipInputStream(stream))
265 var entry = zipStream.GetNextEntry();
270 var buffer =
new byte[entry.Size];
271 await zipStream.ReadAsync(buffer, 0, (
int)entry.Size).ConfigureAwait(
false);
274 var str = (encoding ?? Encoding.ASCII).GetString(buffer);
275 data[entry.Name] = str;
285 catch (Exception err)
298 public static byte[]
ZipBytes(
byte[] bytes,
string zipEntryName)
300 using var memoryStream =
new MemoryStream();
301 ZipBytesAsync(memoryStream, bytes, zipEntryName,
null).ConfigureAwait(
false).GetAwaiter().GetResult();
302 return memoryStream.ToArray();
314 public static async Task
ZipBytesAsync(Stream target,
byte[] data,
string zipEntryName, ZipArchiveMode? mode =
null,
315 CompressionLevel? compressionLevel =
null)
317 await
ZipBytesAsync(target, [
new KeyValuePair<
byte[],
string>(data, zipEntryName)], mode, compressionLevel).ConfigureAwait(
false);
328 public static async Task
ZipBytesAsync(Stream target, IEnumerable<KeyValuePair<
byte[],
string>> data, ZipArchiveMode? mode =
null,
329 CompressionLevel? compressionLevel =
null)
331 compressionLevel ??= CompressionLevel.SmallestSize;
332 using var archive =
new ZipArchive(target, mode ?? ZipArchiveMode.Create,
true);
333 foreach (var kvp
in data)
335 var entry = archive.CreateEntry(kvp.Value, compressionLevel.Value);
336 using var entryStream = entry.Open();
337 await entryStream.WriteAsync(kvp.Key).ConfigureAwait(
false);
349 public static async Task
ZipStreamsAsync(
string target, IEnumerable<KeyValuePair<string, Stream>> data, ZipArchiveMode? mode =
null,
350 CompressionLevel? compressionLevel =
null)
352 using var fileStream = mode == ZipArchiveMode.Update
353 ?
new FileStream(target, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)
354 :
new FileStream(target, FileMode.Create, FileAccess.Write, FileShare.None);
355 await
ZipStreamsAsync(fileStream, data, mode, compressionLevel).ConfigureAwait(
false);
367 public static async Task
ZipStreamsAsync(Stream target, IEnumerable<KeyValuePair<string, Stream>> data, ZipArchiveMode? mode =
null,
368 CompressionLevel? compressionLevel =
null,
bool leaveStreamOpen =
false)
370 compressionLevel ??= CompressionLevel.SmallestSize;
371 using var archive =
new ZipArchive(target, mode ?? ZipArchiveMode.Create, leaveStreamOpen);
372 foreach (var kvp
in data)
374 if (archive.Mode == ZipArchiveMode.Update)
376 var existingEntry = archive.GetEntry(kvp.Key);
377 existingEntry?.Delete();
379 var entry = archive.CreateEntry(kvp.Key, compressionLevel.Value);
380 using var entryStream = entry.Open();
381 await kvp.Value.CopyToAsync(entryStream).ConfigureAwait(
false);
390 public static string UnGZip(
string gzipFileName,
string targetDirectory)
393 var dataBuffer =
new byte[4096];
394 var newFileOutput = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(gzipFileName));
395 using (Stream fileStream =
new FileStream(gzipFileName, FileMode.Open, FileAccess.Read))
396 using (var gzipStream =
new GZipInputStream(fileStream))
397 using (var fileOutput = File.Create(newFileOutput))
399 StreamUtils.Copy(gzipStream, fileOutput, dataBuffer);
401 return newFileOutput;
411 public static string Zip(
string textPath,
string zipEntryName,
bool deleteOriginal =
true)
413 var zipPath = textPath.Replace(
".csv",
".zip").Replace(
".txt",
".zip");
414 Zip(textPath, zipPath, zipEntryName, deleteOriginal);
425 public static void Zip(
string source,
string destination,
string zipEntryName,
bool deleteOriginal)
429 var buffer =
new byte[4096];
430 using (var stream =
new ZipOutputStream(File.Create(destination)))
433 var entry =
new ZipEntry(zipEntryName);
434 stream.PutNextEntry(entry);
436 using (var fs = File.OpenRead(source))
441 sourceBytes = fs.Read(buffer, 0, buffer.Length);
442 stream.Write(buffer, 0, sourceBytes);
444 while (sourceBytes > 0);
454 catch (Exception err)
466 public static string Zip(
string textPath,
bool deleteOriginal =
true)
468 return Zip(textPath, Path.GetFileName(textPath), deleteOriginal);
477 public static void Zip(
string data,
string zipPath,
string zipEntry)
479 using (var stream =
new ZipOutputStream(File.Create(zipPath)))
481 var entry =
new ZipEntry(zipEntry);
482 stream.PutNextEntry(entry);
483 var buffer =
new byte[4096];
484 using (var dataReader =
new MemoryStream(Encoding.Default.GetBytes(data)))
489 sourceBytes = dataReader.Read(buffer, 0, buffer.Length);
490 stream.Write(buffer, 0, sourceBytes);
492 while (sourceBytes > 0);
504 public static bool ZipDirectory(
string directory,
string destination,
bool includeRootInZip =
true)
508 if (File.Exists(destination)) File.Delete(destination);
509 System.IO.Compression.ZipFile.CreateFromDirectory(directory, destination, CompressionLevel.Fastest, includeRootInZip,
new PathEncoder());
512 catch (Exception err)
522 private class PathEncoder : UTF8Encoding
524 public override byte[] GetBytes(
string s)
526 s = s.Replace(
"\\",
"/");
527 return base.GetBytes(s);
537 public static bool Unzip(
string zip,
string directory,
bool overwrite =
false)
539 if (!File.Exists(zip))
return false;
545 System.IO.Compression.ZipFile.ExtractToDirectory(zip, directory);
549 using (var archive =
new ZipArchive(File.OpenRead(zip)))
551 foreach (var file
in archive.Entries)
554 if (
string.IsNullOrEmpty(file.Name))
continue;
555 var filepath = Path.Combine(directory, file.FullName);
556 if (IsLinux) filepath = filepath.Replace(
@"\",
"/");
557 var outputFile =
new FileInfo(filepath);
558 if (!outputFile.Directory.Exists)
560 outputFile.Directory.Create();
562 file.ExtractToFile(outputFile.FullName,
true);
569 catch (Exception err)
579 public static void ZipFiles(
string destination, IEnumerable<string> files)
583 using (var zipStream =
new ZipOutputStream(File.Create(destination)))
585 var buffer =
new byte[4096];
586 foreach (var file
in files)
588 if (!File.Exists(file))
590 Log.
Trace($
"ZipFiles(): File does not exist: {file}");
594 var entry =
new ZipEntry(Path.GetFileName(file));
595 zipStream.PutNextEntry(entry);
596 using (var fstream = File.OpenRead(file))
598 StreamUtils.Copy(fstream, zipStream, buffer);
603 catch (Exception err)
616 public static StreamReader
Unzip(
string filename, out ZipFile zip)
618 return Unzip(filename,
null, out zip);
629 public static StreamReader
Unzip(
string filename,
string zipEntryName, out ZipFile zip)
631 StreamReader reader =
null;
636 if (File.Exists(filename))
640 zip =
new ZipFile(filename);
641 var entry = zip.FirstOrDefault(x => zipEntryName ==
null ||
string.Compare(x.FileName, zipEntryName, StringComparison.OrdinalIgnoreCase) == 0);
648 reader =
new StreamReader(entry.OpenReader());
650 catch (Exception err)
653 if (zip !=
null) zip.Dispose();
654 if (reader !=
null) reader.Close();
659 Log.
Error($
"Data.UnZip(2): File doesn\'t exist: {filename}");
662 catch (Exception err)
664 Log.
Error(err,
"File: " + filename);
680 public static IEnumerable<KeyValuePair<string, List<string>>>
Unzip(
string filename)
682 if (!File.Exists(filename))
684 Log.
Error($
"Compression.Unzip(): File does not exist: {filename}");
685 return Enumerable.Empty<KeyValuePair<string, List<string>>>();
690 return ReadLinesImpl(filename);
692 catch (Exception err)
696 return Enumerable.Empty<KeyValuePair<string, List<string>>>();
705 public static IEnumerable<KeyValuePair<string, List<string>>>
Unzip(Stream stream)
707 using (var zip = ZipFile.Read(stream))
709 foreach (var entry
in zip)
711 yield
return new KeyValuePair<string, List<string>>(entry.FileName, ReadZipEntry(entry));
723 if (!File.Exists(filename))
725 Log.
Error($
"Compression.ReadFirstZipEntry(): File does not exist: {filename}");
726 return new List<string>();
731 return ReadLinesImpl(filename, firstEntryOnly:
true).Single().Value;
733 catch (Exception err)
737 return new List<string>();
740 private static IEnumerable<KeyValuePair<string, List<string>>> ReadLinesImpl(
string filename,
bool firstEntryOnly =
false)
742 using (var zip = ZipFile.Read(filename))
744 for (var i = 0; i < zip.Count; i++)
747 yield
return new KeyValuePair<string, List<string>>(entry.FileName, ReadZipEntry(entry));
756 private static List<string> ReadZipEntry(Ionic.Zip.ZipEntry entry)
758 var result =
new List<string>();
759 using var entryReader =
new StreamReader(entry.OpenReader());
760 var line = entryReader.ReadLine();
764 line = entryReader.ReadLine();
774 StreamReader reader =
null;
781 using (var zipStream =
new ZipInputStream(zipstream))
784 var entry = zipStream.GetNextEntry();
785 var buffer =
new byte[entry.Size];
786 zipStream.Read(buffer, 0, (
int)entry.Size);
789 file =
new MemoryStream(buffer);
793 reader =
new StreamReader(file);
795 catch (Exception err)
806 public static Stream
UnzipStream(Stream zipstream, out ZipFile zipFile,
string entryName =
null)
808 zipFile = ZipFile.Read(zipstream);
812 Ionic.Zip.ZipEntry entry;
813 if (
string.IsNullOrEmpty(entryName))
816 entry = zipFile.Entries.FirstOrDefault();
821 if (!zipFile.ContainsEntry(entryName))
825 entry = zipFile[entryName];
830 return entry.OpenReader();
833 catch (Exception err)
847 public static List<string>
UnzipToFolder(
byte[] zipData,
string outputFolder)
849 var stream =
new MemoryStream(zipData);
860 var outFolder = Path.GetDirectoryName(zipFile);
861 var stream = File.OpenRead(zipFile);
871 private static List<string>
UnzipToFolder(Stream dataStream,
string outFolder)
874 var files =
new List<string>();
875 if (
string.IsNullOrEmpty(outFolder))
877 outFolder = Directory.GetCurrentDirectory();
879 ICSharpCode.SharpZipLib.Zip.ZipFile zf =
null;
883 zf =
new ICSharpCode.SharpZipLib.Zip.ZipFile(dataStream);
885 foreach (ZipEntry zipEntry
in zf)
888 if (!zipEntry.IsFile)
continue;
890 var buffer =
new byte[4096];
891 var zipStream = zf.GetInputStream(zipEntry);
894 var fullZipToPath = Path.Combine(outFolder, zipEntry.Name);
896 var targetFile =
new FileInfo(fullZipToPath);
897 if (targetFile.Directory !=
null && !targetFile.Directory.Exists)
899 targetFile.Directory.Create();
903 files.Add(fullZipToPath);
906 using (var streamWriter =
File.Create(fullZipToPath))
908 StreamUtils.Copy(zipStream, streamWriter, buffer);
915 Log.
Error($
"Compression.UnzipToFolder(): Failure: outFolder: {outFolder} - files: {string.Join(",
", files)}");
922 zf.IsStreamOwner =
true;
934 public static void UnTarFiles(
string source,
string destination)
936 var inStream = File.OpenRead(source);
937 var tarArchive = TarArchive.CreateInputTarArchive(inStream);
938 tarArchive.ExtractContents(destination);
950 var inStream = File.OpenRead(source);
951 var gzipStream =
new GZipInputStream(inStream);
952 var tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
953 tarArchive.ExtractContents(destination);
965 public static IEnumerable<KeyValuePair<string, byte[]>>
UnTar(Stream stream,
bool isTarGz)
967 using (var tar =
new TarInputStream(isTarGz ? (Stream)
new GZipInputStream(stream) : stream))
970 while ((entry = tar.GetNextEntry()) !=
null)
972 if (entry.IsDirectory)
continue;
974 using (var output =
new MemoryStream())
976 tar.CopyEntryContents(output);
977 yield
return new KeyValuePair<string, byte[]>(entry.Name, output.ToArray());
988 public static IEnumerable<KeyValuePair<string, byte[]>>
UnTar(
string source)
991 var gzip = (source.Substring(Math.Max(0, source.Length - 6)) ==
"tar.gz");
993 using (var file = File.OpenRead(source))
995 var tarIn =
new TarInputStream(file);
999 var gzipStream =
new GZipInputStream(file);
1000 tarIn =
new TarInputStream(gzipStream);
1004 while ((tarEntry = tarIn.GetNextEntry()) !=
null)
1006 if (tarEntry.IsDirectory)
continue;
1008 using (var stream =
new MemoryStream())
1010 tarIn.CopyEntryContents(stream);
1011 yield
return new KeyValuePair<string, byte[]>(tarEntry.Name, stream.ToArray());
1025 using (var zip =
new ICSharpCode.SharpZipLib.Zip.ZipFile(path))
1027 return zip.TestArchive(
true);
1038 using (var zip = ZipFile.Read(zipFileName))
1040 return zip.EntryFileNames;
1051 using (var zip = ZipFile.Read(zipFileStream))
1053 return zip.EntryFileNames;
1066 var zipper = IsLinux ?
"7z" :
"C:/Program Files/7-Zip/7z.exe";
1067 var psi =
new ProcessStartInfo(zipper,
" e " + inputFile +
" -o" + outputDirectory)
1069 CreateNoWindow =
true,
1070 WindowStyle = ProcessWindowStyle.Hidden,
1071 UseShellExecute =
false,
1072 RedirectStandardOutput =
false
1075 var process =
new Process();
1076 process.StartInfo = psi;
1079 if (!process.WaitForExit(execTimeout))
1081 throw new TimeoutException($
"Timed out extracting 7Zip archive: {inputFile} ({execTimeout} seconds)");
1083 if (process.ExitCode > 0)
1085 throw new Exception($
"Compression.Extract7ZipArchive(): 7Zip exited unsuccessfully (code {process.ExitCode})");