어떻게 C\#로 압축 파일 을 실현 합 니까?

11203 단어 C#압축 파일
단일 파일 압축
장면,파일 이 비교적 클 수 있 으 므 로 업로드 와 다운로드 등 압축 전송 이 필요 합 니 다.

/// <summary>
///      
/// </summary>
/// <param name="sourceFile">   </param>
/// <param name="zipedFile">zip    </param>
/// <param name="blockSize">     </param>
/// <param name="compressionLevel">    </param>
public static void ZipFile(string sourceFile, string zipedFile, int blockSize = 1024, int compressionLevel = 6)
{
    if (!File.Exists(sourceFile))
    {
        throw new System.IO.FileNotFoundException("The specified file " + sourceFile + " could not be found.");
    }
    var fileName = System.IO.Path.GetFileNameWithoutExtension(sourceFile);

    FileStream streamToZip = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
    FileStream zipFile = File.Create(zipedFile);
    ZipOutputStream zipStream = new ZipOutputStream(zipFile);

    ZipEntry zipEntry = new ZipEntry(fileName);
    zipStream.PutNextEntry(zipEntry);

    //  、  、  、  、  、    0-9
    zipStream.SetLevel(compressionLevel);

    byte[] buffer = new byte[blockSize];

    int size = streamToZip.Read(buffer, 0, buffer.Length);
    zipStream.Write(buffer, 0, size);
    try
    {
        while (size < streamToZip.Length)
        {
            int sizeRead = streamToZip.Read(buffer, 0, buffer.Length);
            zipStream.Write(buffer, 0, sizeRead);
            size += sizeRead;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    zipStream.Finish();
    zipStream.Close();
    streamToZip.Close();
}
설명:26 줄,blocksize 는 캐 시 영역 크기 입 니 다.너무 크게 설정 할 수 없습니다.너무 크 면 이상 을 보고 할 수 있 습 니 다.26-38 줄,파일 을 FileStream 흐름 을 통 해 버퍼 에 읽 고 Zip Output Stream 흐름 에 기록 합 니 다.두 개의 파이프,하 나 는 읽 고,다른 하 나 는 쓰 고,중간 은 버퍼 이 며,그들의 작업 방식 은 동기 화 방식 이 라 고 상상 할 수 있다.다른 방식 으로 일 할 수 있 는 지 생각해 보 세 요.읽 는 파 이 프 는 읽 기만 하고 쓴 파 이 프 는 쓰기 만 할 수 있 습 니까?만약 에 이런 장면 이 라면 읽 는 것 이 매우 빠 르 고 쓰 는 것 이 비교적 느리다.예 를 들 어 로 컬 쓰기 가 아니 라 네트워크 를 통 해 전송 해 야 하기 때문에 비동기 적 인 방식 을 고려 할 수 있다.어떻게 하면 독자 가 스스로 개조 할 수 있 습 니까?중요 한 것 은 흐름 은 순서 가 있 기 때문에 순서 의 정확성 을 확보 하면 된다.
다 중 파일 압축
이런 장면 도 비교적 많이 볼 수 있 는데 단일 파일 의 압축 과 유사 하 다.단지 몇 번 더 순환 하 는 것 일 뿐이다.

/// <summary>
///      
/// </summary>
/// <param name="zipfile">zip    </param>
/// <param name="filenames">     </param>
/// <param name="password">    </param>
public void ZipFiles(string zipfile, string[] filenames, string password = "")
{
    ZipOutputStream s = new ZipOutputStream(System.IO.File.Create(zipfile));

    s.SetLevel(6);

    if (password != "")
        s.Password = Md5Help.Encrypt(password);

    foreach (string file in filenames)
    {
        //      
        FileStream fs = File.OpenRead(file);

        byte[] buffer = new byte[fs.Length];
        fs.Read(buffer, 0, buffer.Length);

        var name = Path.GetFileName(file);

        ZipEntry entry = new ZipEntry(name);
        entry.DateTime = DateTime.Now;
        entry.Size = fs.Length;
        fs.Close();
        s.PutNextEntry(entry);
        s.Write(buffer, 0, buffer.Length);
    }
    s.Finish();
    s.Close();
}
설명:21 줄,버퍼 크기 가 파일 크기 이기 때문에 한 번 에 읽 고 쓰 지 않 았 습 니 다.이런 상황 에서 단일 파일 은 1G 를 초과 하 는 것 과 같이 너무 크 면 안 된다.14 줄,압축 패키지 에 비밀 번 호 를 설정 할 수 있 습 니 다.MD5 생 성 방법 은 다음 과 같 습 니 다.

public class Md5Help
{
    /// <summary>
    ///32  MD5  
    /// </summary>
    /// <param name="str">    </param>
    /// <returns></returns>
    public static string Encrypt(string str)
    {
        MD5 md5 = new MD5CryptoServiceProvider();

        byte[] encryptdata = md5.ComputeHash(Encoding.UTF8.GetBytes(str));

        return Convert.ToBase64String(encryptdata);
    }
}
3.다 중 파일 비동기 압축
위 에서 동기 화 된 압축 의 전 제 는 파일 이 크 지 않 고 파일 수가 많 지 않다 고 가정 하 는 것 이다.그러나 현실 은 파일 만 크 지 않 고 파일 수가 많다 는 것 이다.이런 상황 에 서 는 비동기 적 인 방법 을 고려 해 야 한다.그렇지 않 으 면 메 인 스 레 드 를 막 을 것 이다.바로 우리 가 평소에 말 하 는 카드 죽음 이다.

/// <summary>
///        zip   
/// </summary>
/// <param name="zipfile">       </param>
/// <param name="filenames">    </param>
public static async void ZipFilesAsync(string zipfile, string[] filenames)
{
    await Task.Run(() =>
    {
        ZipOutputStream s = null;
        try
        {
            s = new ZipOutputStream(System.IO.File.Create(zipfile));

            s.SetLevel(6); // 0 - store only to 9 - means best compression 

            foreach (string file in filenames)
            {
                //       
                FileStream fs = System.IO.File.OpenRead(file);

                var name = Path.GetFileName(file);
                ZipEntry entry = new ZipEntry(name);
                entry.DateTime = DateTime.Now;
                entry.Size = fs.Length;
                s.PutNextEntry(entry);

                //      1G
                long blockSize = 51200;

                var size = (int)fs.Length;

                var oneG = 1024 * 1024 * 1024;

                if (size > oneG)
                {
                    blockSize = oneG;
                }
                byte[] buffer = new byte[blockSize];

                size = fs.Read(buffer, 0, buffer.Length);

                s.Write(buffer, 0, size);

                while (size < fs.Length)
                {
                    int sizeRead = fs.Read(buffer, 0, buffer.Length);
                    s.Write(buffer, 0, sizeRead);
                    size += sizeRead;
                }
                s.Flush();
                fs.Close();
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("        :" + ex.Message);
        }
        finally
        {
            s?.Finish();
            s?.Close();
        }
    });
}
압축 파일
실제 응용 프로그램 에 서 는 파일 과 폴 더 를 함께 압축 하기 때문에 이 경우 아예 압축 할 물건 을 모두 폴 더 에 넣 고 압축 한다.
주 방법 은 다음 과 같다.

/// <summary>
///         zip   
/// </summary>
/// <param name="zipfile">       </param>
/// <param name="sourceFolder">       </param>
/// <param name="filenames">    </param>
public static async void ZipFolderAsync(string zipfile, string sourceFolder, string[] filenames)
{
    await Task.Run(() =>
    {
        ZipOutputStream s = null;
        try
        {
            s = new ZipOutputStream(System.IO.File.Create(zipfile));

            s.SetLevel(6); // 0 - store only to 9 - means best compression 

            CompressFolder(sourceFolder, s, sourceFolder);
        }
        catch (Exception ex)
        {
            Console.WriteLine("        :" + ex.Message);
        }
        finally
        {
            s?.Finish();
            s?.Close();
        }
    });
}
압축 의 핵심 방법:

/// <summary>
///      
/// </summary>
/// <param name="source">   </param>
/// <param name="s">ZipOutputStream  </param>
/// <param name="parentPath"> source  </param>
public static void CompressFolder(string source, ZipOutputStream s, string parentPath)
{
    string[] filenames = Directory.GetFileSystemEntries(source);
    foreach (string file in filenames)
    {
        if (Directory.Exists(file))
        {
            CompressFolder(file, s, parentPath);  //        
        }
        else
        {
            using (FileStream fs = System.IO.File.OpenRead(file))
            {
                var writeFilePath = file.Replace(parentPath, "");
                ZipEntry entry = new ZipEntry(writeFilePath);
                entry.DateTime = DateTime.Now;
                entry.Size = fs.Length;

                s.PutNextEntry(entry);

                //      1G
                long blockSize = 51200;

                var size = (int)fs.Length;

                var oneG = 1024 * 1024 * 1024;

                if (size > oneG)
                {
                    blockSize = oneG;
                }
                byte[] buffer = new byte[blockSize];

                size = fs.Read(buffer, 0, buffer.Length);

                s.Write(buffer, 0, size);


                while (size < fs.Length)
                {
                    int sizeRead = fs.Read(buffer, 0, buffer.Length);
                    s.Write(buffer, 0, sizeRead);
                    size += sizeRead;
                }

                s.Flush();   //       ,               
                fs.Close();
            }
        }
    }
}
유일 하 게 주의해 야 할 점 은 압축 을 풀 수 있 는 디 렉 터 리 구조 와 압축 전의 파일 디 렉 터 리 가 다 를 수 있 습 니 다.이 때 parentPath 인 자 를 검사 합 니 다.ZipEntry 실체 new 를 사용 할 때 절대 경 로 를 현재 의 상대 경로 로 바 꿉 니 다.즉,상대 적 으로 압축 된 폴 더 의 경로 입 니 다.
위의 방법 은 비교적 복잡 하고 상대 적 으로 간단 한 방식 도 있 습 니 다.api 를 직접 호출 합 니 다.

public static string ZipFolder(string sourceFolder, string zipFile)
{
    string result = "";
    try
    {
        //     
        if (!Directory.Exists(sourceFolder)) return result = "        ";

        DirectoryInfo d = new DirectoryInfo(sourceFolder);
        var files = d.GetFiles();
        if (files.Length == 0)
        {
            //    
            var ds = d.GetDirectories();
            if (ds.Length > 0)
            {
                files = ds[0].GetFiles();
            }
        }
        if (files.Length == 0) return result = "       ";
        System.IO.Compression.ZipFile.CreateFromDirectory(sourceFolder, zipFile);
    }
    catch (Exception ex)
    {
        result += "    :" + ex.Message;
    }
    return result;
}
이상 은 어떻게 C\#로 압축 파일 을 실현 하 는 지 에 대한 상세 한 내용 입 니 다.C\#압축 파일 에 관 한 자 료 는 다른 관련 글 에 주목 하 십시오!

좋은 웹페이지 즐겨찾기