• .Net Framework 2.0中的Compression功能


    以前做项目的时候,需要提供文件压缩功能。当时是使用了一个开源的类库,名为ZipLib,使用起来还是很方便的。我还在自己的英文博客上post了一篇文章《ZipLib Works Well! 》也许是看到了这个功能的必要性,在.Net 2.0中,微软在System.IO中新增了System.IO.Compression命名空间,提供了压缩功能的相关类GZipStream。

    这个类的使用与一般的文件流使用差不多。我没有分析其内部实现,但猜测应该还是采用Decorator模式对Stream进行了装饰,从中应用了Compression算法。它通过Write()方法,将buffer里面的内容写到另一个文件流中,例如源文件为sourceFile,压缩后的文件为targetFile,则方法为:
    byte[] buffer = null;
    FileStream sourceStream 
    = null;
    FileStream targetStream 
    = null;
    GZipStream compressedStream 
    = null;

    sourceStream 
    = new FileStream(sourceFile,FileMode.Open,FileAccess.Read,FileShare.Read);
    buffer 
    = new byte[sourceStream.Length];
    sourceStream.Read(buffer,
    0,buffer.Length);

    targetStream 
    = new FileStream(targetFile,FileMode.OpenOrCreate,FileAccess.Write);
    //将CompressedStream指向targetStream;
    compressedStream = new GZipStream(targetStream,CompressionMode.Compress,true);
    compressStream.Write(buffer,
    0,buffer.Length);

    在使用GZipStream时,需要添加引用:

    using System.IO;
    using System.IO.Compression;

    解压缩与前面的方法差不多,仍然使用GZipStream文件流:

    // Read in the compressed source stream
    sourceStream = new FileStream ( sourceFile, FileMode.Open );

    // Create a compression stream pointing to the destiantion stream
    decompressedStream = new GZipStream ( sourceStream, CompressionMode.Decompress, true );

    // Read the footer to determine the length of the destiantion file
    quartetBuffer = new byte[4];
    int position = (int)sourceStream.Length - 4;
    sourceStream.Position 
    = position;
    sourceStream.Read ( quartetBuffer, 
    04 );
    sourceStream.Position 
    = 0;
    int checkLength = BitConverter.ToInt32 ( quartetBuffer, 0 );

    byte[] buffer = new byte[checkLength + 100];

    int offset = 0;
    int total = 0;

    // Read the compressed data into the buffer
    while ( true )
    {
                 
    int bytesRead = decompressedStream.Read ( buffer, offset, 100 );

                 
    if ( bytesRead == 0 )
                            
    break;

                 offset 
    += bytesRead;
                 total 
    += bytesRead;
      }


      
    // Now write everything to the destination file
      destinationStream = new FileStream ( destinationFile, FileMode.Create );
      destinationStream.Write ( buffer, 
    0, total );

      
    // and flush everyhting to clean out the buffer
      destinationStream.Flush ( );

    .Net 2.0中除了提供GZipStream外,还提供了DeflateStream类,它仍然具有压缩的功能,只是采用的压缩算法不同而已。

    using System;
    using System.IO;
    using System.IO.Compression;

    public class DeflateTest
    {
        
    public static int ReadAllBytesFromStream(Stream stream, byte[] buffer) 
        
    {
        
    // Use this method is used to read all bytes from a stream.
        int offset = 0;
        
    int totalCount = 0;
            
    while (true
            
    {
            
    int bytesRead = stream.Read(buffer, offset, 100); 
                
    if ( bytesRead == 0
                
    {
                
    break
                }

        offset 
    += bytesRead;
        totalCount 
    += bytesRead; 
            }

        
    return totalCount;
        }
     

        
    public static bool CompareData(byte[] buf1, int len1, byte[] buf2, int len2) 
        
    {
            
    // Use this method to compare data from two different buffers.
            if (len1 != len2) 
            

            Console.WriteLine(
    "Number of bytes in two buffer are different {0}:{1}", len1, len2);
            
    return false;
            }


            
    for ( int i= 0; i< len1; i++
            
    {
                
    if ( buf1[i] != buf2[i]) 
                
    {
                Console.WriteLine(
    "byte {0} is different {1}|{2}", i, buf1[i], buf2[i]);
                
    return false;
                }

            }

        Console.WriteLine(
    "All bytes compare.");
        
    return true
        }


        
    public static void DeflateCompressDecompress(string filename)
        
    {
        Console.WriteLine(
    "Test compression and decompression on file {0}", filename);
        FileStream infile;
            
    try
            
    {
            
    // Open the file as a FileStream object.
            infile = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            
    byte[] buffer = new byte[infile.Length];
            
    // Read the file to ensure it is readable.
            int count = infile.Read(buffer, 0, buffer.Length);
                
    if ( count != buffer.Length) 
                
    {
                infile.Close();
                Console.WriteLine(
    "Test Failed: Unable to read data from file"); 
                
    return;
                }

            infile.Close();
            MemoryStream ms 
    = new MemoryStream();
            
    // Use the newly created memory stream for the compressed data.
            DeflateStream compressedzipStream = new DeflateStream(ms , CompressionMode.Compress, true);
            Console.WriteLine(
    "Compression");
            compressedzipStream.Write(buffer, 
    0, buffer.Length);
            
    // Close the stream.
            compressedzipStream.Close();
            Console.WriteLine(
    "Original size: {0}, Compressed size: {1}", buffer.Length, ms.Length);

            
    // Reset the memory stream position to begin decompression.
            ms.Position = 0;
            DeflateStream zipStream 
    = new DeflateStream(ms, CompressionMode.Decompress);
            Console.WriteLine(
    "Decompression");
            
    byte[] decompressedBuffer = new byte[buffer.Length + 100];
            
    // Use the ReadAllBytesFromStream to read the stream.
            int totalCount = DeflateTest.ReadAllBytesFromStream(zipStream, decompressedBuffer);
            Console.WriteLine(
    "Decompressed {0} bytes", totalCount);

            
    if!DeflateTest.CompareData(buffer, buffer.Length, decompressedBuffer, totalCount) ) 
            
    {
            Console.WriteLine(
    "Error. The two buffers did not compare.");
            }

        zipStream.Close(); 
            }
     // end try
            catch (InvalidDataException)
            
    {
                Console.WriteLine(
    "Error: The file being read contains invalid data.");
            }

            
    catch (FileNotFoundException)
            
    {
                Console.WriteLine(
    "Error:The file specified was not found.");
            }

            
    catch (ArgumentException)
            
    {
                Console.WriteLine(
    "Error: path is a zero-length string, contains only white space, or contains one or more invalid characters");
            }

            
    catch (PathTooLongException)
            
    {
                Console.WriteLine(
    "Error: The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.");
            }

            
    catch (DirectoryNotFoundException)
            
    {
                Console.WriteLine(
    "Error: The specified path is invalid, such as being on an unmapped drive.");
            }

            
    catch (IOException)
            
    {
                Console.WriteLine(
    "Error: An I/O error occurred while opening the file.");
            }

            
    catch (UnauthorizedAccessException)
            
    {
                Console.WriteLine(
    "Error: path specified a file that is read-only, the path is a directory, or caller does not have the required permissions.");
            }

            
    catch (IndexOutOfRangeException)
            
    {
                Console.WriteLine(
    "Error: You must provide parameters for MyGZIP.");
            }

        }

        
    public static void Main(string[] args)
        
    {
            
    string usageText = "Usage: DeflateTest <inputfilename>";
            
    //If no file name is specified, write usage text.
            if (args.Length == 0)
            
    {
                Console.WriteLine(usageText);
            }

            
    else
            
    {
                
    if (File.Exists(args[0]))
                    DeflateCompressDecompress(args[
    0]);
            }

        }

    }


     


    微软在加入GZipSream和DeflateStream后,使得.Net对文件流的支持更加丰富。我们也可以直接利用.Net Framework 2.0写出自己的压缩程序了。

    本文的代码部分来自Visual Studio 2005 101Sample C#.
  • 相关阅读:
    Linux系统的tomcat以daemon模式启动并配置成服务202004
    HBuilder android 开发者证书的生成20200416
    【office相关问题】Excel无法打开文件xxx.xlsx,因为文件格式或文件扩展名无效。请确定文件未损坏解决办法
    RHEL6.4服务器整体迁移记录RHEL6.9-2020-操作系统安装在M2固态,应用/数据库重要数据安装至DELL-H310阵列卡RAID1上保证数据安全性
    Linux下将自己安装的Apache(httpd)新增为系统服务,开机自启动
    Linux安装mysql(解压版)tar包解压安装(靠谱版)
    koa2实现jwt登录
    详解js数组扁平化
    快速掌握ES6 iterator Generator和async 之间的关系及其用法
    快速掌握ES6的class用法
  • 原文地址:https://www.cnblogs.com/wayfarer/p/221101.html
Copyright © 2020-2023  润新知