我的压缩方法中的额外字符从何而来?

发布于 2024-12-10 22:13:42 字数 1627 浏览 0 评论 0原文

我有一个压缩和解压缩方法,用于添加额外的空字符。我设法修复了它,但我不确定为什么修复有效,希望有人可以向我解释一下。

修复(下一行中 buffer.length 的 -1):

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length - 1), 0, gzBuffer, 0, 4)

原始行:

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length), 0, gzBuffer, 0, 4)

功能:

Private Function Compress(ByVal bytes As Byte()) As Byte()
    Using ms As New MemoryStream()

        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestCompression, True)
            zip.Write(bytes, 0, bytes.Length)
        End Using

        //ms.Position = 0
        Dim compressed As Byte() = ms.ToArray()

        Dim gzBuffer(compressed.Length + 4) As Byte
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length)
        System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length -1), 0, gzBuffer, 0, 4)

        Return gzBuffer
    End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()

    Using ms As New MemoryStream()
        Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
        ms.Write(bytes, 4, bytes.Length - 4)

        Dim buffer(msgLength) As Byte

        ms.Position = 0
        Dim offset As Integer = 0
        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
            While offset < buffer.Length - 1
                offset += zip.Read(buffer, offset, buffer.Length - offset)
            End While
        End Using

        Return buffer
    End Using
End Function

I had a compress and a decompress method that used to add an extra empty character. I managed to fix it, but I'm not sure why the fixed worked and hope somebody could explain it to me.

The Fix (-1 from buffer.length in the following line):

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length - 1), 0, gzBuffer, 0, 4)

Original line:

System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length), 0, gzBuffer, 0, 4)

The Functions:

Private Function Compress(ByVal bytes As Byte()) As Byte()
    Using ms As New MemoryStream()

        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestCompression, True)
            zip.Write(bytes, 0, bytes.Length)
        End Using

        //ms.Position = 0
        Dim compressed As Byte() = ms.ToArray()

        Dim gzBuffer(compressed.Length + 4) As Byte
        System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length)
        System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length -1), 0, gzBuffer, 0, 4)

        Return gzBuffer
    End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()

    Using ms As New MemoryStream()
        Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
        ms.Write(bytes, 4, bytes.Length - 4)

        Dim buffer(msgLength) As Byte

        ms.Position = 0
        Dim offset As Integer = 0
        Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
            While offset < buffer.Length - 1
                offset += zip.Read(buffer, offset, buffer.Length - offset)
            End While
        End Using

        Return buffer
    End Using
End Function

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

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

发布评论

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

评论(1

时光病人 2024-12-17 22:13:42

更好了,现在长度不会覆盖部分压缩数据。

现在您的问题是您没有正确使用 Stream.Read 方法。该方法返回读取的字节数,该数可能小于请求的字节数,因此您必须获取该返回值并重复读取,直到获得所有数据:

Dim offset as Integer = 0
Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
  Do While offset < buffer.Length
    offset += zip.Read(buffer, offset, buffer.Length - offset)
  Loop
End Using

此外,不要将字节数组写入内存流,只需从数组创建内存流:

Using ms As New MemoryStream(bytes)

无需将内存流读入数组,只需使用 ToArray 方法:

Dim compressed As Byte() = ms.ToArray()

编辑:

代码中的一次性问题是由于数组的方式造成的在VB中创建,使用最高索引而不是大小,所以应使用以下方式创建缓冲区:

Dim buffer(msgLength - 1) As Byte

在读取和写入内存流时使用 Position 属性可以避免创建额外的缓冲区:(

Private Function Compress(ByVal bytes As Byte()) As Byte()
  Using ms As New MemoryStream()
    ms.Position = 4
    Using zip As New GZipStream(ms, CompressionMode.Compress, True)
      zip.Write(bytes, 0, bytes.Length)
    End Using
    ms.Position = 0
    ms.Write(BitConverter.GetBytes(bytes.Length), 0, 4)
    Return ms.ToArray()
  End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()
  Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
  Using ms As New MemoryStream(bytes)
    Dim buffer(msgLength - 1) As Byte
    ms.Position = 4
    Dim offset As Integer = 0
    Using zip As New GZipStream(ms, CompressionMode.Decompress)
      While offset < buffer.Length
        offset += zip.Read(buffer, offset, buffer.Length - offset)
      End While
    End Using
    Return buffer
  End Using
End Function

注意:此代码使用标准 .NET GZipStream。 )

That's better, now the length doesn't overwrite part of the compressed data.

Now your problem is that you are not using the Stream.Read method correctly. The method returns the number of bytes read, which can be less than the number of bytes requested, so you have to get that return value and repeat the read until you have all the data:

Dim offset as Integer = 0
Using zip As New Ionic.Zlib.GZipStream(ms, Ionic.Zlib.CompressionMode.Decompress)
  Do While offset < buffer.Length
    offset += zip.Read(buffer, offset, buffer.Length - offset)
  Loop
End Using

Also, instead of writing a byte array to the memory stream, just create the memory stream from the array:

Using ms As New MemoryStream(bytes)

Instead of reading the memory stream into an array, just use the ToArray method:

Dim compressed As Byte() = ms.ToArray()

Edit:

The one-off problem in the code was due to how arrays are created in VB, using the highest index instead of the size, so the buffer should be created using:

Dim buffer(msgLength - 1) As Byte

Using the Position property when reading and writing the memory stream you can avoid creating extra buffers:

Private Function Compress(ByVal bytes As Byte()) As Byte()
  Using ms As New MemoryStream()
    ms.Position = 4
    Using zip As New GZipStream(ms, CompressionMode.Compress, True)
      zip.Write(bytes, 0, bytes.Length)
    End Using
    ms.Position = 0
    ms.Write(BitConverter.GetBytes(bytes.Length), 0, 4)
    Return ms.ToArray()
  End Using
End Function

Private Function DeCompress(ByVal bytes As Byte()) As Byte()
  Dim msgLength As Integer = BitConverter.ToInt32(bytes, 0)
  Using ms As New MemoryStream(bytes)
    Dim buffer(msgLength - 1) As Byte
    ms.Position = 4
    Dim offset As Integer = 0
    Using zip As New GZipStream(ms, CompressionMode.Decompress)
      While offset < buffer.Length
        offset += zip.Read(buffer, offset, buffer.Length - offset)
      End While
    End Using
    Return buffer
  End Using
End Function

(Note: This code uses the standard .NET GZipStream.)

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