我在互联网上看到了很多示例代码,展示了如何在文件系统上压缩和解压缩文件,还有很多关于如何存储常规 SQL Server数据库中的文件,但从不同时。这是我到目前为止的代码。 (我在VB.NET中使用实体框架,但这不是重点。我希望。)
Private Sub ButtonStore_Click(sender As Object, e As EventArgs) Handles ButtonStore.Click
Dim db As New Storage
Dim bld = db.Builds.Find(1)
Dim ecfg_file = New FileStream("D:\Temp\X1_450_1750_60207003.ecfg", FileMode.Open)
Dim sr = New StreamReader(ecfg_file)
Dim contents = sr.ReadToEnd
Dim ms = New MemoryStream()
Dim comp_stream = New GZipStream(ms, CompressionMode.Compress)
Dim sw = New StreamWriter(comp_stream)
sw.Write(contents)
sw.Flush()
comp_stream.Flush()
ms.Flush()
bld.EcfgFile = ms.ToArray()
db.SaveChanges()
db.Dispose()
ecfg_file.Close()
comp_stream.Close()
ms.Close()
End Sub
Private Sub ButtonExtract_Click(sender As Object, e As EventArgs) Handles ButtonExtract.Click
Dim db As New Storage
Dim bld = db.Builds.Find(1)
Dim ecfg_file = New FileStream("D:\Temp\asdf.ecfg", FileMode.Create)
Dim ms As New MemoryStream()
ms.Write(bld.EcfgFile.ToArray, 0, bld.EcfgFile.Length)
ms.Position = 0
Dim decompression_stream = New GZipStream(ms, CompressionMode.Decompress, True)
Dim sr = New StreamReader(decompression_stream)
Dim asdf = sr.ReadToEnd
Dim sw = New StreamWriter(ecfg_file)
sw.Write(asdf)
ecfg_file.Close()
decompression_stream.Close()
ms.Close()
End Sub
这非常接近。问题是,在提取时,文件会覆盖自身的一部分,或者停止缩短。原始文件为18,613 KB,存储和提取的文件为18,446 KB。我甚至不知道在存储或提取过程中是否出现问题。
正如您所看到的,我正在尝试.Flush
和.Close()
所有内容以确保所有内容都正确完成。 (是的,我可以尝试Using
,但我不喜欢它最终会产生的所有缩进。)
答案 0 :(得分:1)
简短回答:
您可能会发现CLR运行时函数,例如DeflateStream(this article中的示例实现)和GZipStream非常有用。
答案很长:
我假设您将文件存储在varbinary(max)列中的数据库中,而且从Kornelis收集的内容中,SQL Server不能以您希望的方式压缩大对象(LOB)数据它与页面压缩(或行压缩,或列存储索引,我假设扩展到columnstore_archive)。作者基本上指出这是因为跨越多个页面的数据(当然LOB数据会自然会这样)不会受益于这种类型的压缩。
我正在寻找类似的解决方案,到目前为止,我倾向于使用CLR函数进行压缩,基本上在将数据写入表之前压缩数据,并在读取数据后进行解压缩。这会带来影响,但据我理解,就像无法在压缩数据上使用某些搜索功能一样 - 根据Henderson - 无法再对它进行异步读/写操作。
答案 1 :(得分:0)
Plutonix使用Using
块清理对象是正确的,而Max Vernon可能对代码的可读性是正确的。
这有效:
Private Sub ButtonStore_Click(sender As Object, e As EventArgs) Handles ButtonStore.Click
Dim contents As String
Using ecfg_file = New FileStream("C:\Temp\X1_450_1750_60207003.ecfg", FileMode.Open)
Using sr = New StreamReader(ecfg_file)
contents = sr.ReadToEnd
End Using
End Using
Using ms = New MemoryStream()
Using comp_stream = New GZipStream(ms, CompressionMode.Compress)
Using sw = New StreamWriter(comp_stream)
sw.Write(contents)
End Using
End Using
Using db As New Storage
Dim bld = db.Builds.First
bld.EcfgFile = ms.ToArray()
db.SaveChanges()
End Using
End Using
Debug.Print("Done")
End Sub
Private Sub ButtonExtract_Click(sender As Object, e As EventArgs) Handles ButtonExtract.Click
Dim contents As String
Using db As New Storage
Dim bld = db.Builds.First
Using ms = New MemoryStream()
ms.Write(bld.EcfgFile.ToArray, 0, bld.EcfgFile.Length)
ms.Position = 0
Using decompression_stream = New GZipStream(ms, CompressionMode.Decompress, True)
Using sr = New StreamReader(decompression_stream)
contents = sr.ReadToEnd
End Using
End Using
End Using
End Using
Using ecfg_file = New FileStream("C:\Temp\asdf.ecfg", FileMode.Create)
Using sw = New StreamWriter(ecfg_file)
sw.Write(contents)
End Using
End Using
Debug.Print("Done")
End Sub