' 以小尾序(Little-Endian)字节顺序来读取一个不带符号的 short 基础数据流。 PrivateFunction ReadLeInt16()As Int16 Dim i As Int16 =CType(ReadLeByte(), Int16) Dim j As Int16 =CType(ReadLeByte(), Int16) Return(i Or(j << 8)) EndFunction 'ReadLeInt16
' 以小尾序(Little-Endian)字节顺序来读取一个 int 基底数据流。 PrivateFunction ReadLeInt32()As Int32 Dim ui As Int32 Dim uj As Int32 ui =CType(ReadLeInt16(), Int32) uj =CType(ReadLeInt16(), Int32) If(ui < 0)Then ui = System.Math.Pow(2, 16)+ ui EndIf Return(ui Or(uj << 16)) EndFunction 'ReadLeInt32
' 从压缩文件读取下一个项目并返回其描述。 PrivateFunction GetNextEntry()As ZipEntry Dim currentEntry As ZipEntry =Nothing Try Dim size As Int32 = ReadLeInt32() If size =-1 Then ReturnNew ZipEntry(String.Empty) EndIf Dim csize As Int32 = ReadLeInt32() Dim crc(15)AsByte ReadBuf(crc, crc.Length)
Dim dostime As Int32 = ReadLeInt32() Dim nameLength As Int16 = ReadLeInt16()
Dim buffer(nameLength - 1)AsByte ReadBuf(buffer, nameLength) Dim name AsString= ConvertToString(buffer)
currentEntry =New ZipEntry(name) currentEntry.Size = size currentEntry.CompressedSize = csize currentEntry.SetCrc(crc) currentEntry.DosTime = dostime Catch ex As ArgumentException ZipConstants.ShowError(ZipConstants.ArgumentError) Catch ex As ObjectDisposedException ZipConstants.ShowError(ZipConstants.CloseError) EndTry Return currentEntry EndFunction 'GetNextEntry
' 将未压缩数据写入项目中的文件名称。 ' 它会初始化一个内存数据流来作为暂存处,并且使用 Gzip 数据流 ' 或 Deflate 数据流来解压缩它。 PrivateSub WriteUncompressedFile(ByVal entry As ZipEntry,ByVal completePath AsString) Dim ms AsNew MemoryStream() Try Dim b(entry.CompressedSize - 1)AsByte baseStream.Read(b, 0,CType(entry.CompressedSize,Integer)) If CheckCRC(entry.GetCrc(), b)Then ms.Write(b, 0, b.Length) EndIf ms.Seek(0, SeekOrigin.Begin) If Method = ZipConstants.DEFLATE Then zipStream =New DeflateStream(ms, CompressionMode.Decompress,False) ElseIf Method = ZipConstants.GZIP Then zipStream =New GZipStream(ms, CompressionMode.Decompress,False) EndIf
Dim index AsInteger= entry.Name.LastIndexOf(ZipConstants.BackSlash) Dim name AsString= completePath + entry.Name.Substring(index + 1) Dim rewrite AsNew FileStream(name, FileMode.Create) b =NewByte(entry.Size - 1){} zipStream.Read(b, 0,CType(entry.Size,Integer))
rewrite.Write(b, 0,CType(entry.Size,Integer)) rewrite.Close() Catch ex As IOException ZipConstants.ShowError(ZipConstants.IOError) Catch ex As ArgumentException ZipConstants.ShowError(ZipConstants.ArgumentError) Finally zipStream.Close() ms.Close() EndTry EndSub 'WriteUncompressedFile
' 解压缩清单中的所有项目。 ' 清单可能是空的。 PublicSub ExtractAll(ByVal zipEntries As List(Of ZipEntry), _ ByVal startPath AsString) Try Dim dir AsNew DirectoryInfo(startPath + zipName) IfNot dir.Exists Then dir.Create() EndIf Dim jump AsInteger= 3 baseStream.Seek(jump, SeekOrigin.Begin)
Dim entry As ZipEntry ForEach entry In zipEntries Dim index1 AsInteger= entry.Name.IndexOf(ZipConstants.BackSlash) Dim index2 AsInteger= entry.Name.LastIndexOf(ZipConstants.BackSlash) Dim relPath AsString= entry.Name.Substring(index1 + 1, index2 - index1) If index1 = 0 Then relPath =String.Empty EndIf If relPath.Length <> 0 Then dir.CreateSubdirectory(relPath) EndIf jump = ZipConstants.FixedHeaderSize + entry.NameLength baseStream.Seek(jump, SeekOrigin.Current) WriteUncompressedFile(entry, startPath + zipName + ZipConstants.BackSlash + relPath) Next entry CH2_DemoForm002.statusMessage =String.Format(System.Threading.Thread.CurrentThread.CurrentUICulture, ZipConstants.ExtractMessage, startPath + zipName + ZipConstants.BackSlash) Catch ex As IOException ZipConstants.ShowError(ZipConstants.IOError) Catch ex As OutOfMemoryException ZipConstants.ShowError(ZipConstants.MemoryError) EndTry EndSub