FileCompression.NET
사용하는 곳이 많지는 않겠지만, 예전에 작업해 놓은게 있어서 소스를 정리해서 올립니다.
Unix에서 사용하는 압축형식 중 Z, Tgz, Tar의 압축을 해제하는 소스코드 입니다.
evenZip, SharpZipLib, 7zip 의 3가지 외부 라이브러리를 사용했으며,
7zip의 경우 C#용 dll이 아니므로 해당 dll을 사용하는 LzwInputStream.cs를 포함시켰습니다.
- Z file :
7z.dll
andLzwInputStream.cs
- Zip file : SharpZipLib
- Tgz file : SevenZip
- Tar file : SharpZipLib
* 2016-04-08 수정
- UnTgz를 Thread Safe한 코드로 수정하였습니다. 방법을 알려주신 Alex Lee ( https://www.facebook.com/csharpstudy )님께 감사드립니다.
* 2016-04-11 수정
- UnTgz의 Event가 재사용 가능성이 희박한 코드라서 Lambda식으로 수정하였습니다. Pull Request 주신 Bongho Lee님 (https://github.com/techcap) 님께 감사드립니다.
전체 소스 및 Project 설정 사항은 아래 Link를 참고해 주세요.
- UnTgz를 Thread Safe한 코드로 수정하였습니다. 방법을 알려주신 Alex Lee ( https://www.facebook.com/csharpstudy )님께 감사드립니다.
* 2016-04-11 수정
- UnTgz의 Event가 재사용 가능성이 희박한 코드라서 Lambda식으로 수정하였습니다. Pull Request 주신 Bongho Lee님 (https://github.com/techcap) 님께 감사드립니다.
전체 소스 및 Project 설정 사항은 아래 Link를 참고해 주세요.
* 소스코드
using ICSharpCode.SharpZipLib.Tar; using ICSharpCode.SharpZipLib.Zip; using SevenZip; using System; using System.Collections.Generic; using System.IO; // 솔루션 빌드 후 이벤트에 아래 줄 추가 (단 최종경로 확인 필수 : Project명에 . 들어가는 경우 실제 폴더 구조랑 다를 수 있음 // COPY /Y "$(SolutionDir)$(ProjectName)\7z.dll" "$(SolutionDir)$(SolutionName)\$(OutDir)\7z.dll" namespace LunaStar.Util { public class FileCompression { /// <summary> /// Unix에서 생성한 Z 파일의 압축해제 /// </summary> /// <param name="zFileName">압축해제할 Z 파일이름</param> /// <returns>압축 해제 성공 여부</returns> static public bool UnUnixZ(string zFileName) { try { FileInfo fi = new FileInfo(zFileName); string directoryName = fi.DirectoryName; string fileName = Path.GetFileNameWithoutExtension(zFileName); string outputFileName = $"{directoryName}\\{fileName}"; using (Stream inStream = new LzwInputStream(File.OpenRead(zFileName))) using (FileStream outStream = File.Create(outputFileName)) { int bytesRead; byte[] buffer = new byte[4096]; while ((bytesRead = inStream.Read(buffer, 0, buffer.Length)) > 0) { outStream.Write(buffer, 0, bytesRead); } } } catch (Exception e) { throw new AggregateException("Fail FileCompression.UnUnixZ", e); } return true; } /// <summary> /// 특정 폴더를 ZIP으로 압축 /// </summary> /// <param name="targetFolderPath">압축 대상 폴더 경로</param> /// <param name="zipFilePath">저장할 ZIP 파일 경로</param> /// <param name="password">압축 암호</param> /// <param name="isDeleteFolder">폴더 삭제 여부</param> /// <returns>압축 성공 여부</returns> public static bool Zip(string targetFolderPath, string zipFilePath, string password, bool isDeleteFolder) { if (!Directory.Exists(targetFolderPath)) // 폴더가 존재하는 경우에만 수행 return false; List<string> fileList = GenerateFileList(targetFolderPath); // 압축 대상 폴더의 파일 목록 int pathLength = (Directory.GetParent(targetFolderPath)).ToString().Length + 1; // find number of chars to remove. from orginal file path. remove '\' using (ZipOutputStream zipOutputStream = new ZipOutputStream(File.Create(zipFilePath))) // ZIP 스트림 생성. { if (password != null && password != string.Empty) // 패스워드가 있는 경우 패스워드 지정 zipOutputStream.Password = password; zipOutputStream.SetLevel(9); // 암호화 레벨.(최대 압축) ZipEntry zipEntry; foreach (string fileName in fileList) { zipEntry = new ZipEntry(fileName.Remove(0, pathLength)); zipOutputStream.PutNextEntry(zipEntry); try { if (!fileName.EndsWith(@"/")) // 파일인 경우 { using (FileStream fileStream = File.OpenRead(fileName)) { byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); zipOutputStream.Write(buffer, 0, buffer.Length); } } } catch (Exception e) { // 오류가 난 경우 생성 했던 파일을 삭제. if (File.Exists(zipFilePath)) File.Delete(zipFilePath); throw new AggregateException("FileCompression.Zip : Fail to ZipOutputStream", e); } finally { zipOutputStream.Finish(); // 압축 종료 zipOutputStream.Close(); } } } if (isDeleteFolder) // 폴더 삭제를 원할 경우 폴더 삭제 { try { Directory.Delete(targetFolderPath, true); } catch (Exception e) { throw new AggregateException("FileCompression.Zip : Fail to delete folder", e); } } return true; } /// <summary> /// 파일, 폴더 목록 생성 /// </summary> /// <param name="directory">폴더 경로</param> /// <returns>폴더, 파일 목록(ArrayList)</returns> private static List<string> GenerateFileList(string directory) { var fileList = new List<string>(); bool isEmpty = true; try { foreach (string fileName in Directory.GetFiles(directory)) // 폴더 내의 파일 추가 { fileList.Add(fileName); isEmpty = false; } } catch (Exception e) { throw new AggregateException("FileCompression.GenetateFileList : Fail to add files", e); } if (isEmpty) { try { if (Directory.GetDirectories(directory).Length == 0) // 파일이 없고, 폴더도 없는 경우 자신의 폴더 추가 fileList.Add(directory + @"/"); } catch (Exception e) { throw new AggregateException("FileCompression.GenetateFileList : Fail to add self", e); } } try { foreach (string directoryName in Directory.GetDirectories(directory)) // 폴더 내 폴더 목록 { foreach (string fileName in GenerateFileList(directoryName)) // 해당 폴더로 다시 GenerateFileList 재귀 호출 { fileList.Add(fileName); // 해당 폴더 내의 파일, 폴더 추가 } } } catch (Exception e) { throw new AggregateException("FileCompression.GenetateFileList : Fail to add directories", e); } return fileList; } /// <summary> /// ZIP 압축 파일 풀기 /// </summary> /// <param name="zipFilePath">ZIP파일 경로</param> /// <param name="unZipTargetFolderPath">압축 풀 폴더 경로</param> /// <param name="password">해지 암호</param> /// <param name="isDeleteZipFile">zip파일 삭제 여부</param> /// <returns>압축 풀기 성공 여부 </returns> public static bool Unzip(string zipFilePath, string unZipTargetFolderPath, string password, bool isDeleteZipFile) { if (!File.Exists(zipFilePath)) // ZIP 파일이 있는 경우만 수행 return false; using (ZipInputStream zipInputStream = new ZipInputStream(File.OpenRead(zipFilePath))) // ZIP 스트림 생성 { if (password != null && password != string.Empty) // 패스워드가 있는 경우 패스워드 지정 zipInputStream.Password = password; try { ZipEntry theEntry; while ((theEntry = zipInputStream.GetNextEntry()) != null) // 반복하며 파일을 가져옴 { string directoryName = Path.GetDirectoryName(theEntry.Name); // 폴더 명칭 string fileName = Path.GetFileName(theEntry.Name); // 파일 명칭 Directory.CreateDirectory(unZipTargetFolderPath + directoryName); // 폴더 생성 if (fileName == string.Empty) // 파일 이름이 없으면 Pass continue; using (FileStream streamWriter = File.Create((unZipTargetFolderPath + theEntry.Name))) // 파일 스트림 생성.(파일생성) { byte[] data = new byte[2048]; while (true) // 파일 복사 { int size = zipInputStream.Read(data, 0, data.Length); if (size > 0) streamWriter.Write(data, 0, size); else break; } streamWriter.Close(); // 파일스트림 종료 } } } catch (Exception e) { throw new AggregateException("FileCompression.Unzip : Fail to ZipInputStream", e); } finally { zipInputStream.Close(); // ZIP 파일 스트림 종료 } } if (isDeleteZipFile) // ZIP파일 삭제를 원할 경우 파일 삭제 { try { File.Delete(zipFilePath); } catch (Exception e) { throw new AggregateException("FileCompression.Unzip : Fail to delete zip file", e); } } return true; } /// <summary> /// tgz 파일 압축 풀기 /// </summary> /// <param name="fileName">tgz 파일명</param> /// <param name="savePath">저장할 파일 위치</param> /// <returns>압축 풀기 성공 여부 </returns> public static bool UnTgz(string fileName, string savePath) { if (!File.Exists(fileName)) return false; using (SevenZipExtractor sevenZipExtractor = new SevenZipExtractor(fileName)) { try { sevenZipExtractor.EventSynchronization = EventSynchronizationStrategy.AlwaysSynchronous; savePath = savePath.Replace(@"\\", @"\"); sevenZipExtractor.ExtractionFinished += (sender, e) => { try { List<string> fileList = GenerateFileList(savePath); foreach (string file in fileList) { var fi = new FileInfo(file); if (fi.Extension.ToUpper() == ".TAR") { UnTar(file); fi.Delete(); } } } catch (Exception ex) { throw new AggregateException("FileCompression.ExtractionFinishedHandler : Fail sevenZipExtractor", ex); } }; sevenZipExtractor.ExtractArchive(savePath); } catch (Exception e) { throw new AggregateException("FileCompression.UnTgz : Fail sevenZipExtractor", e); } } return true; } /// <summary> /// tar 파일 압축 해제 /// </summary> /// <param name="TarName">tar 파일명</param> public static void UnTar(string TarName) { try { FileInfo fi = new FileInfo(TarName); using (TarInputStream s = new TarInputStream(File.OpenRead(TarName))) { TarEntry theEntry; while ((theEntry = s.GetNextEntry()) != null) { string FullName = string.Format("{0}\\{1}", fi.DirectoryName, theEntry.Name); string DirName = Path.GetDirectoryName(FullName); string FileName = Path.GetFileName(FullName); if (!Directory.Exists(DirName)) Directory.CreateDirectory(DirName); if (FileName != string.Empty) { FileStream SW = File.Create(FullName); int Size = 2048; byte[] data = new byte[2048]; while (true) { Size = s.Read(data, 0, data.Length); if (Size > 0) SW.Write(data, 0, Size); else break; } SW.Close(); } } } } catch (Exception e) { throw new AggregateException("FileCompression.UnTar : Fail untar", e); } } } }
댓글 없음:
댓글 쓰기