.net 在我的压缩方法中,额外的字符来自哪里?
我有一个压缩和解压缩方法,用来添加一个额外的空字符。我设法把它修好了,但我不知道为什么修好了,希望有人能给我解释一下 修复程序(-1 from buffer.length,在下一行中): 原始行:.net 在我的压缩方法中,额外的字符来自哪里?,.net,compression,.net,Compression,我有一个压缩和解压缩方法,用来添加一个额外的空字符。我设法把它修好了,但我不知道为什么修好了,希望有人能给我解释一下 修复程序(-1 from buffer.length,在下一行中): 原始行: System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length), 0, gzBuffer, 0, 4) 职能: Private Function Compress(ByVal bytes As Byte()) As Byte() Usi
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
Private函数压缩(ByVal字节为Byte())为Byte())
将ms用作新内存流()
使用zip作为新的Ionic.Zlib.gzip流(ms、Ionic.Zlib.CompressionMode.Compress、Ionic.Zlib.CompressionLevel.BestCompression,True)
zip.Write(字节,0,字节.长度)
终端使用
//女士职位=0
Dim压缩为Byte()=ms.ToArray()
Dim gzBuffer(compressed.Length+4)作为字节
System.Buffer.BlockCopy(压缩的,0,gzBuffer,4,压缩的.Length)
System.Buffer.BlockCopy(BitConverter.GetBytes(bytes.Length-1)、0、gzBuffer、0、4)
返回缓冲区
终端使用
端函数
私有函数解压缩(ByVal字节为Byte())为Byte()
将ms用作新内存流()
Dim msgLength As Integer=位转换器.ToInt32(字节,0)
ms.Write(字节,4,字节.长度-4)
Dim缓冲区(msgLength)作为字节
女士职位=0
尺寸偏移为整数=0
使用zip作为新的Ionic.Zlib.gzip流(ms,Ionic.Zlib.CompressionMode.decompression)
而偏移量<缓冲区长度-1
offset+=zip.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
不要将内存流读入数组,只需使用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
Private函数压缩(ByVal字节为Byte())为Byte())
将ms用作新内存流()
女士职位=4
使用zip作为新的GZipStream(ms,CompressionMode.Compress,True)
zip.Write(字节,0,字节.长度)
终端使用
女士职位=0
ms.Write(位转换器.GetBytes(bytes.Length),0,4)
返回ToArray女士()
终端使用
端函数
私有函数解压缩(ByVal字节为Byte())为Byte()
Dim msgLength As Integer=位转换器.ToInt32(字节,0)
将ms用作新内存流(字节)
Dim缓冲区(msgLength-1)作为字节
女士职位=4
尺寸偏移为整数=0
使用zip作为新的GZipStream(ms,CompressionMode.decompresse)
而偏移量<缓冲区长度
offset+=zip.Read(缓冲区、偏移量、缓冲区长度-偏移量)
结束时
终端使用
返回缓冲区
终端使用
端函数
(注意:此代码使用标准的.NETGZipStream
)如果我必须猜测,我会查看您的流。读取代码(它不检查返回值,或者循环使用较大的偏移量和较小的计数,这两种情况通常都是必需的)@marcGravel我的原始代码中偏移量为4,但是我删除了它们,因为我认为这在.Net中是不必要的(我永远不需要通过查看开头有多少空字节来确定块大小)。你能举个例子说明你的意思吗?我不太清楚。你正在用长度整数覆盖压缩数据的前四个字节。我很惊讶你竟然能得到任何东西。@MrShoubsRead(缓冲区、偏移量、计数)
不保证读取count
字节;它保证读取0(对于EOF),或者>0和@Guffa,我不知道这四个字节是用来做什么的,所以从我发布的代码中删除了它-我现在编辑了这个问题以显示原始代码。它仍然存在完全相同的问题。+1提供了很好的信息,谢谢,但是第一个代码块创建了一个无限循环,因为偏移量永远不会超过14,buffer.length是15(-1,从长度开始,导致了原始的额外字符问题)。同样使用将ms用作新的MemoryStream(bytes)
会在解压缩时导致异常“Bad GZip Header”。我已经更新了我的代码以包含您的更改,但我仍然存在原始问题。另一个问题Guffa-您在评论中说我正在用长度整数覆盖压缩数据的前4个字节。。。我看不到我在哪里做的代码行?你能给我指一下吗(用原来的问题代码,不是现在的问题代码)。@Shoubs先生:你发布的原始代码没有覆盖部分数据,我在回答的第一句话中提到了这一点。我不知道你为什么会得到无限循环。你已经删除了原来的问题,所以我的答案不再有任何意义了(另外,在读写内存流时可以使用Position
,这样就不必创建额外的缓冲区。
Dim buffer(msgLength - 1) As Byte
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