ProjectArcade
202 строки · 7.0 Кб
1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.IO;6using System.Runtime.InteropServices;7
8namespace EmulatorLauncher.Common.Compression9{
10public class ZipArchiveFileEntry11{12private object _entry;13
14public ZipArchiveFileEntry(object zipArchiveEntry)15{16_entry = zipArchiveEntry;17}18
19public System.IO.Stream Open()20{21object obj = _entry.GetType().GetMethod("Open").Invoke(_entry, new object[] { });22return obj as Stream;23}24
25public void Extract(string directory)26{27if (!Directory.Exists(directory))28Directory.CreateDirectory(directory);29
30string path = Path.Combine(directory, Filename);31
32if (IsDirectory)33{34if (!Directory.Exists(path))35Directory.CreateDirectory(path);36
37return;38}39
40using (var stream = Open())41{42if (stream == null)43return;44
45bool canRetry = true;46
47FileStream fileStream = null;48
49retry:50try51{52fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);53}54catch (IOException ex)55{56int errorCode = Marshal.GetHRForException(ex) & ((1 << 16) - 1);57if (canRetry && (errorCode == 32 || errorCode == 33))58{59canRetry = false;60
61try62{63string newName = Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path) + "_");64if (File.Exists(newName))65File.Delete(newName);66
67File.Move(path, newName);68goto retry;69}70catch { throw ex; }71}72}73
74if (fileStream != null)75{76stream.CopyTo(fileStream);77fileStream.Dispose();78}79
80stream.Close();81}82}83
84public string Filename { get; set; }85public bool IsDirectory { get; set; }86public long Length { get; set; }87public DateTime LastModified { get; set; }88public uint Crc32 { get; set; }89
90public string HexCrc91{92get { return Crc32.ToString("x8"); }93}94
95public override string ToString()96{97return Filename;98}99}100
101public class ZipArchive : IDisposable102{103private static System.Reflection.MethodInfo _zipCreateFromDirectory;104
105public static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)106{107if (_zipCreateFromDirectory == null)108{109var afs = System.Reflection.Assembly.Load("System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");110if (afs == null)111throw new Exception("Framework not supported");112
113var ass = System.Reflection.Assembly.Load("System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");114if (ass == null)115throw new Exception("Framework not supported");116
117var zipFile = afs.GetTypes().FirstOrDefault(t => t.Name == "ZipFile");118if (zipFile == null)119throw new Exception("Framework not supported");120
121_zipCreateFromDirectory = zipFile.GetMember("CreateFromDirectory", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).FirstOrDefault() as System.Reflection.MethodInfo;122if (_zipCreateFromDirectory == null)123throw new Exception("Framework not supported");124}125
126_zipCreateFromDirectory.Invoke(null, new object[] { sourceDirectoryName, destinationArchiveFileName });127}128
129private static System.Reflection.MethodInfo _zipOpenRead;130
131private IDisposable _zipArchive;132
133public static ZipArchive OpenRead(string path)134{135if (_zipOpenRead == null)136{137var afs = System.Reflection.Assembly.Load("System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");138if (afs == null)139throw new Exception("Framework not supported");140
141var ass = System.Reflection.Assembly.Load("System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");142if (ass == null)143throw new Exception("Framework not supported");144
145var zipFile = afs.GetTypes().FirstOrDefault(t => t.Name == "ZipFile");146if (zipFile == null)147throw new Exception("Framework not supported");148
149_zipOpenRead = zipFile.GetMember("OpenRead", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).FirstOrDefault() as System.Reflection.MethodInfo;150if (_zipOpenRead == null)151throw new Exception("Framework not supported");152}153
154
155IDisposable zipArchive = _zipOpenRead.Invoke(null, new object[] { path }) as IDisposable;156if (zipArchive == null)157return null;158
159ZipArchive ret = new ZipArchive();160ret._zipArchive = zipArchive;161return ret;162}163
164
165public IEnumerable<ZipArchiveFileEntry> Entries166{167get168{169var entries = _zipArchive.GetType().GetValue<System.Collections.IEnumerable>(_zipArchive, "Entries");170foreach (var entry in entries)171{172var zipArchiveEntry = entry.GetType();173
174string fullName = zipArchiveEntry.GetValue<string>(entry, "FullName");175if (string.IsNullOrEmpty(fullName))176continue;177
178ZipArchiveFileEntry e = new ZipArchiveFileEntry(entry);179e.Filename = fullName;180e.Length = zipArchiveEntry.GetValue<long>(entry, "Length");181e.LastModified = zipArchiveEntry.GetValue<DateTimeOffset>(entry, "LastWriteTime").DateTime;182e.Crc32 = zipArchiveEntry.GetFieldValue<uint>(entry, "_crc32");183
184if (fullName.EndsWith("/"))185{186e.Filename = e.Filename.Substring(0, e.Filename.Length - 1);187e.IsDirectory = true;188}189
190yield return e;191}192}193}194
195public void Dispose()196{197if (_zipArchive != null)198_zipArchive.Dispose();199}200}201
202}
203