При работе с GZip на платформе .NET многие разработчики сталкиваются с проблемой, когда компрессия работает нормально, а при декомпрессии не могут получить исходные данные. На самом деле GZip работает абсолютно нормально, но при одном условии - чтобы декомпрессия работала корректно, нужно знать исходный размер сжимаемых данных.
using System; using System.IO; using System.IO.Compression; using System.Text; namespace Poligon { /// <summary> /// Работа с GZip /// </summary> public class GZip { /// <summary>GZip компрессия файла</summary> /// <param name="fileName">Имя файла с полным путем</param> /// <param name="length">Размер файла до компрессии</param> /// <returns>Массив байтов файла после компрессии</returns> public static byte[] CompressFile(string fileName, out int length) { length = 0; byte[] buffer; if (!File.Exists(fileName)) throw new FileNotFoundException(fileName); using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { buffer = new byte[fs.Length]; for (int i = 0; i < buffer.Length; i++) buffer[i] = (byte)fs.ReadByte(); } length = buffer.Length; byte[] result; using (var ms = new MemoryStream()) { using (var gs = new GZipStream(ms, CompressionMode.Compress)) gs.Write(buffer, 0, buffer.Length); ms.Close(); result = ms.ToArray(); } return result; } /// <summary>GZip декомпрессия файла</summary> /// <param name="fileName">Имя файла с полным путем</param> /// <param name="data">Массив байтов файла до декомпрессии</param> /// <param name="length">Размер файла после декомпрессии</param> /// <returns>Результат создания файла</returns> public static bool DecompressFile(string fileName, byte[] data, int length) { byte[] result; // Распаковать using (var ms = new MemoryStream(data)) using (var gs = new GZipStream(ms, CompressionMode.Decompress)) using (var bs = new MemoryStream()) { var buffer = new byte[length]; int read; while ((read = gs.Read(buffer, 0, buffer.Length)) > 0) bs.Write(buffer, 0, read); bs.Close(); result = bs.ToArray(); } if (File.Exists(fileName)) File.Delete(fileName); using (var fs = new FileStream(fileName, FileMode.CreateNew)) using (var bw = new BinaryWriter(fs)) bw.Write(result); return File.Exists(fileName); } /// <summary>GZip компрессия строки</summary> /// <param name="data">Исходная строка</param> /// <param name="length">Длина строки до компрессии</param> /// <returns>Массив байтов строки после компрессии</returns> public static byte[] CompressString(string data, out int length) { byte[] result = null; byte[] buffer = Encoding.UTF8.GetBytes(data); length = buffer.Length; if (string.IsNullOrEmpty(data)) return result; using (var ms = new MemoryStream()) { using (var gs = new GZipStream(ms, CompressionMode.Compress)) gs.Write(buffer, 0, buffer.Length); ms.Close(); result = ms.ToArray(); } return result; } /// <summary>GZip декомпрессия строки</summary> /// <param name="data">Массив байтов строки до декомпрессии</param> /// <param name="length">Длина строки после декомпрессии</param> /// <returns>Строка после декомпрессии</returns> public static string DecomressString(byte[] data, int length) { if (data != null) { using (var ms = new MemoryStream(data)) using (var gs = new GZipStream(ms, CompressionMode.Decompress)) using (var bs = new MemoryStream()) { var buffer = new byte[length]; int read; while ((read = gs.Read(buffer, 0, buffer.Length)) > 0) bs.Write(buffer, 0, read); bs.Close(); var result = bs.ToArray(); if (result.Length != length) throw new InvalidOperationException(); return Encoding.UTF8.GetString(result); } } return null; } } }
Комментарии
Отправить комментарий