using System.IO.Compression;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Newtonsoft.Json;
///
/// Компрессор для больших списков чисел с плавающей точкой
///
public class CompressedFloatListConverter : ValueConverter, string>
{
public CompressedFloatListConverter()
: base(
v => Compress(v),
v => Decompress(v)
)
{ }
private static string Compress(List list)
{
if (list is null || list.Count == 0)
return "";
byte[] floatBytes = new byte[list.Count * sizeof(float)];
Buffer.BlockCopy(list.ToArray(), 0, floatBytes, 0, floatBytes.Length);
using var outputStream = new MemoryStream();
using (var compressionStream = new BrotliStream(outputStream, CompressionLevel.Optimal))
compressionStream.Write(floatBytes, 0, floatBytes.Length);
return Convert.ToBase64String(outputStream.ToArray());
}
private static List Decompress(string base64String)
{
if (string.IsNullOrEmpty(base64String))
return new List();
byte[] compressedBytes;
float[]? floatArray;
try
{
compressedBytes = Convert.FromBase64String(base64String);
}
catch (FormatException)
{
floatArray = JsonConvert.DeserializeObject(base64String);
if (floatArray is null)
throw;
return new List(floatArray);
}
using var inputStream = new MemoryStream(compressedBytes);
using var decompressionStream = new BrotliStream(inputStream, CompressionMode.Decompress);
using var outputStream = new MemoryStream();
decompressionStream.CopyTo(outputStream);
byte[] decompressedBytes = outputStream.ToArray();
floatArray = new float[decompressedBytes.Length / sizeof(float)];
Buffer.BlockCopy(decompressedBytes, 0, floatArray, 0, decompressedBytes.Length);
return new List(floatArray);
}
}