【问题标题】:Compression to stream压缩到流
【发布时间】:2014-03-19 14:05:10
【问题描述】:

我正在尝试将通过 wcf 发送并解压缩的文件压缩为流。但是,使用以下代码,尝试执行解压缩的 exe 时,我得到的不是有效的 exe。任何解压后的 exe 都比原版低 211-212 字节左右。

Sub Main()

    Dim strm As Stream = CompressToStream("c:\rje\Launcher.exe")

    DecompressToFile(strm)

End Sub

压缩例程

Private Function CompressToStream(ByVal strFullFilename As String) As Stream

    If File.Exists(strFullFilename) Then

        Dim uncompressedfile As New MemoryStream(File.ReadAllBytes(strFullFilename))

        Dim compressedStream As New MemoryStream
        Dim compressionStream As New GZipStream(compressedStream, CompressionMode.Compress)

        uncompressedfile.CopyToStream(compressionStream)
        compressionStream.Flush()
        compressedStream.Position = 0
        Return compressedStream

    End If

    Return Nothing
End Function

使用 .net3.5 复制流的扩展方法

<System.Runtime.CompilerServices.Extension()> _
Private Sub CopyToStream(ByVal input As Stream, ByRef output As Stream)

    Dim Buffer(4096) As Byte
    Dim numRead As Integer = input.Read(Buffer, 0, Buffer.Length)
    Do While numRead <> 0
        output.Write(Buffer, 0, numRead)
        numRead = input.Read(Buffer, 0, Buffer.Length)
    Loop
End Sub

终于解压了

Private Sub DecompressToFile(ByVal strmDownload As Stream)

    Dim spath As String = "c:\rje\text.exe"

    Using outFile As FileStream = File.Create(spath)
        Using Decompress As GZipStream = New GZipStream(strmDownload, CompressionMode.Decompress)
            ' Copy the compressed file into the decompression stream. 

            Dim buffer(4096) As Byte
            Dim numRead As Integer = Decompress.Read(buffer, 0, buffer.Length)
            Do While numRead <> 0
                outFile.Write(buffer, 0, numRead)
                numRead = Decompress.Read(buffer, 0, buffer.Length)
            Loop
        End Using
        outFile.Close()
    End Using
End Sub

如果有人能指出我哪里出错了,那就太好了。

【问题讨论】:

  • 永远不要像那样使用 File.Exists() (第二个代码 sn-p)。只需尝试打开文件,如果失败则处理异常。
  • 什么版本的.Net?
  • @JoelCoehoorn 3.5 vs2008,为什么我不应该使用 File.Exists()?
  • 好吧,你不能在 .Net 4.5 中使用新的 ZipArchive 了 :(
  • 你看过这个示例代码吗? msdn.microsoft.com/en-us/library/… 我问只是因为我想知道以什么为起点。

标签: vb.net gzip


【解决方案1】:

错误与CompressToStream有关,正确修改如下功能

Private Function CompressToStream(ByVal strFullFilename As String) As Stream

    If File.Exists(strFullFilename) Then
        Dim compressedStream As New MemoryStream()
        Using uncompressedfile As New MemoryStream(File.ReadAllBytes(strFullFilename))
            Using compressionStream As New GZipStream(compressedStream, CompressionMode.Compress, True)
                uncompressedfile.CopyToStream(compressionStream)
            End Using
        End Using
        compressedStream.Seek(0, SeekOrigin.Begin)
        Return compressedStream 
    End If

    Return Nothing
End Function

我仍然不知道为什么我不应该使用 File.Exists()?

【讨论】:

  • File.Exists() 只检查存在。它不检查权限,文件是否被另一个进程锁定,或者文件的状态是否在您检查和使用文件之间的短暂空间内发生变化。 (文件系统是不稳定的。以这种方式使用 File.Exists() 会产生竞争条件,即使它很小)。所有这一切的结果是您无论如何都必须处理异常,使 .Exists() 检查在代码维护方面是多余的,并且在额外访问硬盘方面是浪费的(大约是最慢的事情)计算机可以做到)。
  • @JoelCoehoorn 感谢您的解释
【解决方案2】:

这里是我在评论中发布的链接中的示例中改编的 Compress()/Decompress() 方法:

Private Function Compress(ByVal strFullFilename As FileInfo) As Stream
    ' Get the stream of the source file. 
    Dim fi as New FileInfo(strFullFilename)
    Dim result As New MemoryStream() 
    Using inFile As FileStream = fi.OpenRead()
        ' Compressing: 
        ' Prevent compressing hidden and already compressed files. 

        If (File.GetAttributes(fi.FullName) And FileAttributes.Hidden) _
            <> FileAttributes.Hidden And fi.Extension <> ".gz" Then 
            ' Create the compressed file.
            Using Compress As GZipStream = New GZipStream(result, CompressionMode.Compress)
                ' Copy the source file into the compression stream. 
                Dim buffer As Byte() = New Byte(4096) {}
                Dim numRead As Integer = inFile.Read(buffer, 0, buffer.Length)
                Do While numRead <> 0
                    Compress.Write(buffer, 0, numRead)
                    numRead = inFile.Read(buffer, 0, buffer.Length)
                Loop

                'Console.WriteLine("Compressed {0} from {1} to {2} bytes.", fi.Name, fi.Length.ToString(), result.Length.ToString())

            End Using 
        End If 
    End Using 
    Return result
End Sub 

' Method to decompress. 
Private Sub Decompress(ByVal strmDownload As Stream, ByVal resultFileName As String)        

        ' Create the decompressed file. 
        Using outFile As FileStream = File.Create(resultFileName)
            Using Decomp As GZipStream = New GZipStream(strmDownload, CompressionMode.Decompress)
                ' Copy the compressed file into the decompression stream. 
                Dim buffer As Byte() = New Byte(4096) {}
                Dim numRead As Integer = Decompress.Read(buffer, 0, buffer.Length)

                Do While numRead <> 0
                    outFile.Write(buffer, 0, numRead)
                    numRead = Decomp.Read(buffer, 0, buffer.Length)
                Loop
                'Console.WriteLine("Decompressed: {0}", fi.Name)

            End Using 
        End Using 
    End Using 
End Sub 

【讨论】:

  • 我很确定这将返回一个关闭的流,因为 Compress 的“结束使用”将关闭流,使其无法使用
猜你喜欢
  • 2014-03-31
  • 2021-01-19
  • 2011-04-19
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 2018-07-05
  • 2017-11-13
  • 1970-01-01
相关资源
最近更新 更多