Can I decompress and deserialize a file using streams?

前端 未结 2 512
Happy的楠姐
Happy的楠姐 2020-12-02 02:03

My application serializes an object using Json.Net, compresses the resulting JSON, then saves this to file. Additionally the application can load an object from one of these

相关标签:
2条回答
  • 2020-12-02 02:29

    JsonSerializer has methods to serialize from a JsonTextReader and to a StreamWriter, both of which can be created on top of any sort of stream, including a GZipStream. Using them, you can create the following extension methods:

    public static class JsonExtensions
    {
        // Buffer sized as recommended by Bradley Grainger, https://faithlife.codes/blog/2012/06/always-wrap-gzipstream-with-bufferedstream/
        // Do not use a buffer larger than 85,000 bytes since objects larger than that go on the large object heap.  See:
        // https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/large-object-heap
        // Renting a larger array would also be an option, see https://docs.microsoft.com/en-us/dotnet/api/system.buffers.arraypool-1.rent?view=netcore-3.1
        const int BufferSize = 8192;
    
        public static void SerializeToFileCompressed(object value, string path, JsonSerializerSettings settings)
        {
            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)
        {
            using (var compressor = new GZipStream(stream, CompressionMode.Compress))
            using (var writer = new StreamWriter(compressor, Encoding.UTF8, BufferSize))
            {
                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);
            }
        }
    }
    

    See Performance Tips: Optimize Memory Usage in the Json.NET documentation.

    0 讨论(0)
  • 2020-12-02 02:36

    For those looking for an idea how to use the extensions from @dbc in uwp apps, I modified the code to this - where the StorageFile is a file you have access to write to.

    public static async void SerializeToFileCompressedAsync(object value, StorageFile file, JsonSerializerSettings settings = null)
    {
        using (var stream = await file.OpenStreamForWriteAsync())
            SerializeCompressed(value, stream, 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 async Task<T> DeserializeFromFileCompressedAsync<T>(StorageFile file, JsonSerializerSettings settings = null)
    {
        using (var stream = await file.OpenStreamForReadAsync())
            return DeserializeCompressed<T>(stream, 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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题