C# 压缩三字节数组

发布于 2024-08-31 23:14:13 字数 1013 浏览 3 评论 0原文

我目前得到了这个脚本,它压缩字节数组。 但我需要重写它,这样它就可以压缩三字节数组[,,]

谢谢!

public static byte[] Compress(byte[] buffer)
{
MemoryStream ms = new MemoryStream();
GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
zip.Write(buffer, 0, buffer.Length);
zip.Close();
ms.Position = 0;

MemoryStream outStream = new MemoryStream();

byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);

byte[] gzBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return gzBuffer;
}

public static byte[] Decompress(byte[] gzBuffer)
{
MemoryStream ms = new MemoryStream();
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);

byte[] buffer = new byte[msgLength];

ms.Position = 0;
GZipStream zip = new GZipStream(ms, CompressionMode.Decompress);
zip.Read(buffer, 0, buffer.Length);

return buffer;
}

I currently got this script, which compresses byte arrays.
But I need it rewritten, so it can compress triple byte arrays [,,]

Thanks!

public static byte[] Compress(byte[] buffer)
{
MemoryStream ms = new MemoryStream();
GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
zip.Write(buffer, 0, buffer.Length);
zip.Close();
ms.Position = 0;

MemoryStream outStream = new MemoryStream();

byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);

byte[] gzBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return gzBuffer;
}

public static byte[] Decompress(byte[] gzBuffer)
{
MemoryStream ms = new MemoryStream();
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);

byte[] buffer = new byte[msgLength];

ms.Position = 0;
GZipStream zip = new GZipStream(ms, CompressionMode.Decompress);
zip.Read(buffer, 0, buffer.Length);

return buffer;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦萦几度 2024-09-07 23:14:13

更新:我重写了代码,现在运行速度更快了,代码也更干净了。只是用一些随机数据对其进行了测试(请参阅本文末尾)。

压缩方式:

public static byte[] Compress(byte[, ,] uncompressed)
{
    if (uncompressed == null)
        throw new ArgumentNullException("uncompressed", 
                                        "The given array is null!");
    if (uncompressed.LongLength > (long)int.MaxValue)
        throw new ArgumentException("The given array is to large!");

    using (MemoryStream ms = new MemoryStream())
    using (GZipStream gzs = new GZipStream(ms, CompressionMode.Compress))
    {
        // Save sizes of the dimensions
        for (int dim = 0; dim < 3; dim++)
            gzs.Write(BitConverter.GetBytes(
                      uncompressed.GetLength(dim)), 0, sizeof(int));

        // Convert byte[,,] to byte[] by just blockcopying it
        // I know, some pointer-magic/unmanaged cast wouldnt 
        // have to copy it, but its cleaner this way...
        byte[] data = new byte[uncompressed.Length];
        Buffer.BlockCopy(uncompressed, 0, data, 0, uncompressed.Length);

        // Write the data to the stream to compress it
        gzs.Write(data, 0, data.Length);
        gzs.Close();

        // Get the compressed byte array back
        return ms.ToArray();
    }
}

解压方式:

public static byte[, ,] Decompress(byte[] compressed)
{
    if (compressed == null)
        throw new ArgumentNullException("compressed", 
                                        "Data to decompress cant be null!");

    using (MemoryStream ms = new MemoryStream(compressed))
    using (GZipStream gzs = new GZipStream(ms, CompressionMode.Decompress))
    {
        // Read the header and restore sizes of dimensions
        byte[] dimheader = new byte[sizeof(int) * 3];
        gzs.Read(dimheader, 0, dimheader.Length);
        int[] dims = new int[3];
        for (int j = 0; j < 3; j++)
            dims[j] = BitConverter.ToInt32(dimheader, sizeof(int) * j);

        // Read the data into a buffer
        byte[] data = new byte[dims[0] * dims[1] * dims[2]];
        gzs.Read(data, 0, data.Length);

        // Copy the buffer to the three-dimensional array
        byte[, ,] uncompressed = new byte[dims[0], dims[1], dims[2]];
        Buffer.BlockCopy(data, 0, uncompressed, 0, data.Length);

        return uncompressed;
    }
}

测试代码:

Random rnd = new Random();

// Create a new randomly big array, fill it with random data
byte[, ,] uncomp = new byte[rnd.Next(70, 100), 
                       rnd.Next(70, 100), rnd.Next(70, 100)];
for (int x = 0; x < uncomp.GetLength(0); x++)
    for (int y = 0; y < uncomp.GetLength(1); y++)
        for (int z = 0; z < uncomp.GetLength(2); z++)
            uncomp[x, y, z] = (byte)rnd.Next(30, 35);

// Compress and Uncompress again
Stopwatch compTime = new Stopwatch(), uncompTime = new Stopwatch();
compTime.Start();
byte[] comp = Compress(uncomp);
compTime.Stop();
uncompTime.Start();
byte[, ,] uncompagain = Decompress(comp);
uncompTime.Stop();

// Assert all dimension lengths and contents are equal
for (int j = 0; j < 3; j++)
    Debug.Assert(uncomp.GetLength(j) == uncompagain.GetLength(j));

for (int x = 0; x < uncomp.GetLength(0); x++)
    for (int y = 0; y < uncomp.GetLength(1); y++)
        for (int z = 0; z < uncomp.GetLength(2); z++)
            Debug.Assert(uncomp[x, y, z] == uncompagain[x, y, z]);

Console.WriteLine(string.Format("Compression: {0}ms, " +
    "Decompression: {1}ms, Ratio: {2}% ({3}/{4} bytes)",
    compTime.ElapsedMilliseconds, uncompTime.ElapsedMilliseconds,
    (int)((double)comp.LongLength / (double)uncomp.LongLength * 100),
    comp.LongLength, uncomp.LongLength));

输出,例如:

Compression: 77ms, Decompression: 23ms, Ratio: 41% (191882/461538 bytes)

Update: I rewrote the code, it is running much faster now and the code is cleaner. Just tested it with some random data (see end of this post).

The Compression method:

public static byte[] Compress(byte[, ,] uncompressed)
{
    if (uncompressed == null)
        throw new ArgumentNullException("uncompressed", 
                                        "The given array is null!");
    if (uncompressed.LongLength > (long)int.MaxValue)
        throw new ArgumentException("The given array is to large!");

    using (MemoryStream ms = new MemoryStream())
    using (GZipStream gzs = new GZipStream(ms, CompressionMode.Compress))
    {
        // Save sizes of the dimensions
        for (int dim = 0; dim < 3; dim++)
            gzs.Write(BitConverter.GetBytes(
                      uncompressed.GetLength(dim)), 0, sizeof(int));

        // Convert byte[,,] to byte[] by just blockcopying it
        // I know, some pointer-magic/unmanaged cast wouldnt 
        // have to copy it, but its cleaner this way...
        byte[] data = new byte[uncompressed.Length];
        Buffer.BlockCopy(uncompressed, 0, data, 0, uncompressed.Length);

        // Write the data to the stream to compress it
        gzs.Write(data, 0, data.Length);
        gzs.Close();

        // Get the compressed byte array back
        return ms.ToArray();
    }
}

The Decompression method:

public static byte[, ,] Decompress(byte[] compressed)
{
    if (compressed == null)
        throw new ArgumentNullException("compressed", 
                                        "Data to decompress cant be null!");

    using (MemoryStream ms = new MemoryStream(compressed))
    using (GZipStream gzs = new GZipStream(ms, CompressionMode.Decompress))
    {
        // Read the header and restore sizes of dimensions
        byte[] dimheader = new byte[sizeof(int) * 3];
        gzs.Read(dimheader, 0, dimheader.Length);
        int[] dims = new int[3];
        for (int j = 0; j < 3; j++)
            dims[j] = BitConverter.ToInt32(dimheader, sizeof(int) * j);

        // Read the data into a buffer
        byte[] data = new byte[dims[0] * dims[1] * dims[2]];
        gzs.Read(data, 0, data.Length);

        // Copy the buffer to the three-dimensional array
        byte[, ,] uncompressed = new byte[dims[0], dims[1], dims[2]];
        Buffer.BlockCopy(data, 0, uncompressed, 0, data.Length);

        return uncompressed;
    }
}

The test code:

Random rnd = new Random();

// Create a new randomly big array, fill it with random data
byte[, ,] uncomp = new byte[rnd.Next(70, 100), 
                       rnd.Next(70, 100), rnd.Next(70, 100)];
for (int x = 0; x < uncomp.GetLength(0); x++)
    for (int y = 0; y < uncomp.GetLength(1); y++)
        for (int z = 0; z < uncomp.GetLength(2); z++)
            uncomp[x, y, z] = (byte)rnd.Next(30, 35);

// Compress and Uncompress again
Stopwatch compTime = new Stopwatch(), uncompTime = new Stopwatch();
compTime.Start();
byte[] comp = Compress(uncomp);
compTime.Stop();
uncompTime.Start();
byte[, ,] uncompagain = Decompress(comp);
uncompTime.Stop();

// Assert all dimension lengths and contents are equal
for (int j = 0; j < 3; j++)
    Debug.Assert(uncomp.GetLength(j) == uncompagain.GetLength(j));

for (int x = 0; x < uncomp.GetLength(0); x++)
    for (int y = 0; y < uncomp.GetLength(1); y++)
        for (int z = 0; z < uncomp.GetLength(2); z++)
            Debug.Assert(uncomp[x, y, z] == uncompagain[x, y, z]);

Console.WriteLine(string.Format("Compression: {0}ms, " +
    "Decompression: {1}ms, Ratio: {2}% ({3}/{4} bytes)",
    compTime.ElapsedMilliseconds, uncompTime.ElapsedMilliseconds,
    (int)((double)comp.LongLength / (double)uncomp.LongLength * 100),
    comp.LongLength, uncomp.LongLength));

Output, for example:

Compression: 77ms, Decompression: 23ms, Ratio: 41% (191882/461538 bytes)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文