使用7zip sdk压缩文件,但无法使用winrar或7zip解压缩

时间:2011-12-01 09:40:20

标签: c# .net 7zip compression

我从here下载了SDK 7zip。

然后我使用此代码将文件压缩为7zip:

private static void CompressFileLZMA(string inFile, string outFile)
{
    Encoder coder = new SevenZip.Compression.LZMA.Encoder();

    using (FileStream input = new FileStream(inFile, FileMode.Open))
    using (FileStream output = new FileStream(outFile, FileMode.Create))
    {
        coder.Code(input, output, -1, -1, null);
        output.Flush();
    }
}

我在网站上尝试了SDK版本9.20和9.22 beta。

压缩似乎正在压缩我的文件:1.6 MB到239 KB。

但是,如果我使用WinRar或7zip进行解压缩。它们无法识别存档文件,错误就像

  

“未知存档文件或损坏的文件”

对此有何想法?

3 个答案:

答案 0 :(得分:5)

你看过SDK附带的示例项目了吗?它位于CS\7zip\Compress\LzmaAlone\文件夹中,它包含一个文件LmzaAlone.cs,其中包含一些编码文件的内容。它在写出压缩数据之前做了类似的事情:

CoderPropID[] propIDs = 
{
    CoderPropID.DictionarySize,
    CoderPropID.PosStateBits,
    CoderPropID.LitContextBits,
    CoderPropID.LitPosBits,
    CoderPropID.Algorithm,
    CoderPropID.NumFastBytes,
    CoderPropID.MatchFinder,
    CoderPropID.EndMarker
};
object[] properties = 
{
    (Int32)(dictionary),
    (Int32)(posStateBits),
    (Int32)(litContextBits),
    (Int32)(litPosBits),
    (Int32)(algorithm),
    (Int32)(numFastBytes),
    mf,
    eos
};

Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
encoder.SetCoderProperties(propIDs, properties);
encoder.WriteCoderProperties(outStream);
if (trainStream != null)
{
    CDoubleStream doubleStream = new CDoubleStream();
    doubleStream.s1 = trainStream;
    doubleStream.s2 = inStream;
    doubleStream.fileIndex = 0;
    inStream = doubleStream;
    long trainFileSize = trainStream.Length;
    doubleStream.skipSize = 0;
    if (trainFileSize > dictionary)
        doubleStream.skipSize = trainFileSize - dictionary;
    trainStream.Seek(doubleStream.skipSize, SeekOrigin.Begin);
    encoder.SetTrainSize((uint)(trainFileSize - doubleStream.skipSize));
}
// only now does it write out the compressed data:
encoder.Code(inStream, outStream, -1, -1, null);

所以看起来你需要首先写出几个文件头来提供有关压缩数据的详细信息。

如果你下载source for 7Zip,你会发现在doc文件夹中有一个文件7zFormat.txt,其中包含7个zip文件格式的描述。这可能有助于您创建有效的档案。

答案 1 :(得分:3)

它在Stream级别运行的事实表明它只是在执行lzm压缩/解压缩逻辑,并且没有构建实际存档(存档将是.zip或.7z文件)。与使用GZipStreamDeflateStream类似 - 它不会生成存档。像WinRar和7zip这样的工具可以处理档案。

我希望该API中有另一种类型可以实际生成存档,但是会期望更多信息,例如文件名(它几乎肯定会接受多个文件/流)。

答案 2 :(得分:2)

您可以尝试使用7zSharp wrapper或至少分析包装器代码如何完成所有操作。

压缩文件的代码(取自7zSharp):

  public void EncodeSingleFile(string inFile, string outFile)
  {
     using (FileStream inStream = new FileStream(inFile, FileMode.Open, FileAccess.Read))
     {
        using (FileStream outStream = new FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write))
        {
           EncodeSingleFile(inStream, outStream);
        }
     }
  }

  public void EncodeSingleFile(FileStream inStream, FileStream outStream)
  {
     bool eos = false;
     Int32 dictionary = 1 << 21;
     Int32 posStateBits = 2;
     Int32 litContextBits = 3; // for normal files
     // UInt32 litContextBits = 0; // for 32-bit data
     Int32 litPosBits = 0;
     // UInt32 litPosBits = 2; // for 32-bit data
     Int32 algorithm = 2;
     Int32 numFastBytes = 128;
     string mf = "bt4";

     propIDs = new CoderPropID[]
        {
           CoderPropID.DictionarySize,
           CoderPropID.PosStateBits,
           CoderPropID.LitContextBits,
           CoderPropID.LitPosBits,
           CoderPropID.Algorithm,
           CoderPropID.NumFastBytes,
           CoderPropID.MatchFinder,
           CoderPropID.EndMarker
        };
     properties = new object[]
        {
           dictionary,
           posStateBits,
           litContextBits,
           litPosBits,
           algorithm,
           numFastBytes,
           mf,
           eos
        };

     Encoder encoder = new Encoder();
     encoder.SetCoderProperties(propIDs, properties);
     encoder.WriteCoderProperties(outStream);
     Int64 fileSize = inStream.Length;
     for (int i = 0; i < 8; i++)
     {
        outStream.WriteByte((Byte) (fileSize >> (8*i)));
     }
     encoder.Code(inStream, outStream, -1, -1, null);
  }