При работе с 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;
}
}
}
Комментарии
Отправить комментарий