加载压缩文件流的特定部分

时间:2010-05-07 10:00:55

标签: c# .net file compression gzipstream

我们有一个简单的二进制文件格式,用于在我们的应用程序(C#.NET Windows应用程序)中缓存数据。格式基本上是一个short,表示对象类型后跟对象id的guid(字符串),然后是任何对象特定数据(字符串ints无论如何)。我们希望能够在同一文件中存储多个对象(> 10000),但在某些情况下仅按需加载。我们的解决方案是保持文件中对象位置的索引 - 所以当我们开始编写新对象时,我们记录对象开始的文件流中的位置。当我们想要加载此对象时,我们使用此索引位置来加载相关数据。这很好。

但是,如果我们要压缩文件,这个方法仍然可以吗?我对压缩的工作原理并不热,特别是我们计划使用的GZipStream类(System.IO.Compression)。据我了解,这个类不支持Seeking或Position属性。是否仍然可以使用底层FileStream的Seek和Position(我猜不是)?基本上,是否可以有一个我们可以选择加载的压缩文件,如果有的话,我们该如何做?

谢谢,

史蒂夫

3 个答案:

答案 0 :(得分:1)

不,如果您想访问未压缩数据中的特定位置,您必须至少暂时解压缩它

答案 1 :(得分:0)

这不是真正的Seek,但解决方案是:

  • 跟踪你在文件中的位置(最好通过实现继承自BinaryReader的“myBinaryReader”来完成)
  • 如果你正在寻找你当前职位的位置 - ReadBytes,直到你到达那里。
  • 如果您正在寻找当前位置之前的位置 - 重新打开文件以进行解压缩读取(将当前位置重置为零),然后再读取ReadBytes直到达到您想要的位置。

显然,这根本不是一个理想的解决方案,但它仍然可以提供可接受的性能。 在我的例子中,压缩文件很容易适应内存(未压缩的文件没有),所以我已经将压缩文件加载到内存中。

理想情况下,底层的deflate类将被更改为支持真正的Seeks。

答案 2 :(得分:0)

更好的解决方案:

使用GZipStream在内存中创建压缩字节,然后编写自己的类来控制缓存并将其写入磁盘(不要使用DeflateStream)。另外编写自己的类来从磁盘读取这些数据。

然后,您可以确保底层磁盘流支持Seeks。