c# - decompress - ¿Puedo descomprimir y deserializar un archivo usando streams?
zip c# (1)
Mi aplicación serializa un objeto usando Json.Net, comprime el JSON resultante y luego lo guarda en el archivo. Además, la aplicación puede cargar un objeto desde uno de estos archivos. Estos objetos pueden tener decenas de Mb de tamaño y me preocupa el uso de la memoria, debido a la forma en que el código existente crea grandes cadenas y matrices de bytes:
public void Save(MyClass myObject, string filename)
{
var json = JsonConvert.SerializeObject(myObject);
var bytes = Compress(json);
File.WriteAllBytes(filename, bytes);
}
public MyClass Load(string filename)
{
var bytes = File.ReadAllBytes(filename);
var json = Decompress(bytes);
var myObject = JsonConvert.DeserializeObject<MyClass>(json);
}
private static byte[] Compress(string s)
{
var bytes = Encoding.Unicode.GetBytes(s);
using (var ms = new MemoryStream())
{
using (var gs = new GZipStream(ms, CompressionMode.Compress))
{
gs.Write(bytes, 0, bytes.Length);
gs.Close();
return ms.ToArray();
}
}
}
private static string Decompress(byte[] bytes)
{
using (var msi = new MemoryStream(bytes))
{
using (var mso = new MemoryStream())
{
using (var gs = new GZipStream(msi, CompressionMode.Decompress))
{
gs.CopyTo(mso);
return Encoding.Unicode.GetString(mso.ToArray());
}
}
}
}
Me preguntaba si los métodos de Guardar / Cargar podrían ser reemplazados por streams. He encontrado ejemplos de uso de transmisiones con Json.Net pero estoy luchando para entender cómo encajar en la compresión adicional.
JsonSerializer
tiene métodos para serializar desde un JsonTextReader
y un StreamWriter
, ambos se pueden crear sobre cualquier tipo de transmisión, incluido un GZipStream
. Utilizándolos, puede crear los siguientes métodos de extensión:
public static class JsonExtensions
{
public static void SerializeToFileCompressed(object value, string path, JsonSerializerSettings settings = null)
{
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
SerializeCompressed(value, fs, settings);
}
public static void SerializeCompressed(object value, Stream stream, JsonSerializerSettings settings = null)
{
using (var compressor = new GZipStream(stream, CompressionMode.Compress))
using (var writer = new StreamWriter(compressor))
{
var serializer = JsonSerializer.CreateDefault(settings);
serializer.Serialize(writer, value);
}
}
public static T DeserializeFromFileCompressed<T>(string path, JsonSerializerSettings settings = null)
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
return DeserializeCompressed<T>(fs, settings);
}
public static T DeserializeCompressed<T>(Stream stream, JsonSerializerSettings settings = null)
{
using (var compressor = new GZipStream(stream, CompressionMode.Decompress))
using (var reader = new StreamReader(compressor))
using (var jsonReader = new JsonTextReader(reader))
{
var serializer = JsonSerializer.CreateDefault(settings);
return serializer.Deserialize<T>(jsonReader);
}
}
}
Consulte Consejos de rendimiento: Optimice el uso de la memoria en la documentación de Json.NET.