C# LZ4

C# 2021. 10. 20. 18:20

 

 

 

 

 

 

 

 

using K4os.Compression.LZ4;
using K4os.Compression.LZ4.Streams;
using System.IO;

namespace Test
{
    /// <summary>
    /// LZ4 압축 및 해제
    /// 
    /// ex>
    ///     LZ4Compressor.Compress("test-json.txt", "test-json.compress.txt");
    ///     LZ4Compressor.Deompress("test-json.compress.txt", "test-json.uncompress.txt");
    ///     LZ4Compressor.CompressToFile(list, "test-json.compress.txt");
    ///     var obj = LZ4Compressor.DeompressFileTo<List<OrderedDictionary>>("test-json.compress.txt");
    /// </summary>
    public class LZ4Compressor
    {
        public readonly static byte[] MagicNumber = new byte[] { 0x04, 0x22, 0x4D, 0x18 };

        private readonly static LZ4Level s_level = LZ4Level.L12_MAX;

        public static byte[] CompressBytes(byte[] buffer)
        {
            return LZ4Pickler.Pickle(buffer);
        }

        /// <summary>
        /// 파일에 LZ4 의 MagicNumber 가 있는지 확인한다.
        /// LZ4 파일인지 구분하기 위해 사용한다.
        /// MessagePack-CSharp 은 LZ4 를 사용하지만 변형시켜 사용하기 때문에
        /// 첫 4 byte 가 MagicNumber 가 아니다.
        /// </summary>
        /// <param name="path">체크할 파일</param>
        /// <returns>true: LZ4 파일</returns>
        public static bool IsLz4File(string path)
        {
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            using (var br = new BinaryReader(fs))
            {
                return IsEqual(MagicNumber, br.ReadBytes(MagicNumber.Length));
            }
        }

        private static bool IsEqual(byte[] a, byte[] b)
        {
            if (a is null || b is null) return false;
            if (a.Length != b.Length) return false;

            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i])
                {
                    return false;
                }
            }
            return true;
        }

        public static byte[] DecompressBytes(byte[] buffer)
        {
            return LZ4Pickler.Unpickle(buffer);
        }

        public static void CompressFile(string sourcePath, string targetPath)
        {
            using (var source = File.OpenRead(sourcePath))
            using (var target = LZ4Stream.Encode(File.Create(targetPath), s_level))
            {
                source.CopyTo(target);
            }

        }

        public static void DecompressFile(string sourcePath, string targetPath)
        {
            using (var source = LZ4Stream.Decode(File.OpenRead(sourcePath)))
            using (var target = File.Create(targetPath))
            {
                source.CopyTo(target);
            }
        }


        public static void CompressToFile(byte[] bytes, string path)
        {
            using (var source = new MemoryStream(bytes))
            using (var target = LZ4Stream.Encode(File.Create(path), s_level))
            {
                source.CopyTo(target);
            }
        }


        public static byte[] DecompressFile(string path)
        {
            using (var source = LZ4Stream.Decode(File.OpenRead(path)))
            using (var target = new MemoryStream())
            {
                source.CopyTo(target);
                return target.ToArray();
            }
        }


        public static void CompressToFile(MemoryStream source, string path)
        {
            source.Position = 0;
            using (var target = LZ4Stream.Encode(File.Create(path), s_level))
            {
                source.CopyTo(target);
            }
        }


    }
}