Zip压缩包无法完全解压:字节数组解压字节数不符问题
解决SharpZipLib解压时字节数不符的问题
问题根源
你的代码仅调用一次decompressionStream.Read(),但流的Read方法无法保证一次性读取全部数据——它仅返回本次操作实际读取的字节数,当数据量较大或流内部存在缓冲机制时,就会出现读取不完整的情况,导致实际字节数与currentEntry.Size不符。
修正后的代码
Private Function Decompress(ByVal toDecompress As Byte()) As Byte() Dim currentEntrySize As Long Try Using inputStream As New MemoryStream(toDecompress) Using decompressionStream As New ICSharpCode.SharpZipLib.Zip.ZipInputStream(inputStream) Dim currentEntry As Zip.ZipEntry = decompressionStream.GetNextEntry() If currentEntry Is Nothing Then Console.WriteLine("未找到Zip条目") Return Nothing End If currentEntrySize = currentEntry.Size InternalZipFileName = currentEntry.Name ' 处理空文件的情况 If currentEntrySize = 0 Then Return New Byte() {} End If ' 用MemoryStream存储解压结果,避免大文件数组溢出 Using outputStream As New MemoryStream() Dim buffer(4095) As Byte ' 4KB缓冲,平衡效率与内存占用 Dim bytesRead As Integer ' 循环读取直到流结束 Do bytesRead = decompressionStream.Read(buffer, 0, buffer.Length) If bytesRead = 0 Then Exit Do outputStream.Write(buffer, 0, bytesRead) Loop ' 验证最终解压长度是否匹配 If outputStream.Length <> currentEntrySize Then Console.WriteLine($"currentEntrySize <> 实际解压长度 - {currentEntrySize} {outputStream.Length} {InternalZipFileName}") Return Nothing End If Return outputStream.ToArray() End Using End Using End Using Catch ex As Exception Console.WriteLine($"{ex.Message}{vbCrLf}{ex.StackTrace}") Return Nothing End Try End Function
关键修改说明
- 循环读取流数据:通过
Do...Loop持续读取直到流返回0字节,确保所有解压数据被完整读取 - 改用MemoryStream存储:避免因
currentEntry.Size超过Integer.MaxValue导致的数组溢出问题,同时更灵活地处理动态长度数据 - 增加边界处理:添加空Zip条目、空文件的判断逻辑,覆盖更多异常场景
- 使用缓冲数组:4KB大小的缓冲是流操作的常规选择,能平衡读取效率与内存占用
内容的提问来源于stack exchange,提问作者Jim wyman
相关产品推荐
相关产品推荐

