使用7zip SDK压缩文件,但不能使用winrar或7zip解压
本文关键字:7zip winrar 解压 SDK 压缩 文件 使用 但不能 | 更新日期: 2023-09-27 18:16:14
我从这里下载了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测试版。
压缩似乎可以将我的文件从1.6 MB压缩到239 KB。
但是,如果我使用WinRar或7zip来解压。归档文件不能被他们识别,错误如下
"未知存档文件或损坏文件"
有什么想法吗?
您看过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);
所以看起来你需要先写一些文件头来给出即将到来的压缩数据的细节。
如果你下载了7Zip的源代码,那么你会发现在doc文件夹中有一个文件7zFormat.txt
,其中包含了7Zip文件格式的描述。
它在Stream
级别操作的事实表明它只是在执行lzm压缩/解压缩逻辑,而不是构建实际的归档(归档将是.zip或.7z文件)。与使用GZipStream
或DeflateStream
类似,它不会生成存档。像WinRar和7zip这样的工具可以用于归档。
我希望在这个API中有另一种类型可以实际生成存档,但是希望有更多的信息,比如文件名(它几乎肯定也会接受多个文件/流)。
您可以尝试使用7zSharp包装器,或者至少分析包装器代码是如何完成的。
压缩文件的代码(取自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);
}