如何解压动态扩展名的Deflate压缩ANSI编码非.zip格式文件
解决自定义Deflate封装文件的解压与乱码问题
嗨,咱们先把核心问题捋清楚:你碰到的不是单纯的Deflate流压缩,而是用Deflate算法压缩,但套了一层自定义的归档封装(不然7-Zip也没法把它识别成归档文件);至于解压后内容没法正常读取,大概率是因为你用了错误的编码去读取ANSI格式的内容,或者还有额外的解码步骤没做。
结合你提到的技术约束(不能用DeflateStream/GZipStream、DotNetZip引用成本高),给你两个可行的方案:
方案一:用7-Zip命令行工具自动化处理(最省心,无代码依赖)
既然7-Zip能手动打开这个文件,那直接用它的命令行版本7z.exe来处理就好——它已经能识别这个自定义封装的结构,完全绕开.NET库的限制:
- 下载7-Zip的命令行工具(找带
7z.exe的版本,不是带GUI的安装包) - 执行解压命令(把
yourfile.23U换成你的文件名,output_folder换成你要输出的目录):7z x yourfile.23U -ooutput_folder - 读取解压后的文件时,强制用ANSI编码(对应Windows系统的
windows-1252或你本地的系统ANSI编码)来读取,别用默认的UTF-8:// 用系统默认ANSI编码 string content = File.ReadAllText(@"output_folder\extracted_file", Encoding.Default); // 或者指定具体的ANSI编码(比如英文系统常用的1252) string content = File.ReadAllText(@"output_folder\extracted_file", Encoding.GetEncoding(1252));
方案二:手动解析归档头+轻量库处理(纯代码实现)
如果不能依赖7-Zip,那得先搞清楚这个自定义归档的结构:
- 用十六进制编辑器(比如HxD)打开你的
.23U/.23M文件,对比7-Zip解压后的原始字节流,找出归档头的长度(也就是真正的Deflate流开始的位置) - 跳过归档头后,用
ICSharpCode.SharpZipLib这个轻量库处理原始Deflate流(它的引用成本比DotNetZip低很多,MIT许可,NuGet包体积很小):
为什么用SharpZipLib?因为它的using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using System.IO; using System.Text; // 读取文件字节 byte[] fileBytes = File.ReadAllBytes("yourfile.23U"); // 替换成你实际找到的归档头长度(比如16字节,需要自己用十六进制工具分析) int headerLength = 16; using (var ms = new MemoryStream(fileBytes, headerLength, fileBytes.Length - headerLength)) using (var inflaterStream = new InflaterInputStream(ms)) using (var reader = new StreamReader(inflaterStream, Encoding.GetEncoding(1252))) { string content = reader.ReadToEnd(); // 现在content应该是可读的了 }InflaterInputStream能直接处理无Zlib头的原始Deflate流,刚好适配你的场景——而.NET自带的DeflateStream需要标准Zlib头,所以之前用它会失败。
补充:为什么你之前的方法行不通?
DeflateStream:它要求流带有标准的Zlib标识头,而你的文件是原始Deflate流+自定义归档头,所以无法识别GZipStream:只处理带GZip头的.gz文件,完全不匹配你的自定义扩展名文件- 7-Zip能打开:是因为它内置了对这种自定义归档结构的识别,帮你跳过了头并解压了Deflate流,但你用默认UTF-8读取ANSI编码的内容,自然会乱码
如果按上面的方法做了还是乱码,那可能还有额外的加密/字节转换步骤,这时候就得再用十六进制工具对比原始文件和7-Zip解压后的文件,看看有没有XOR加密、字节交换这类操作。
内容的提问来源于stack exchange,提问作者Gaël
相关产品推荐
相关产品推荐

