很抱歉这篇文章很长,我会尽量缩短。
我正在使用一个 json API(当然它的文档为零),它返回如下内容:
{
uncompressedlength: 743637,
compressedlength: 234532,
compresseddata: "lkhfdsbjhfgdsfgjhsgfjgsdkjhfgj"
}
数据(在本例中为 xml)被压缩,然后是我尝试提取的 Base64 编码数据。我所拥有的只是他们用 perl 编写的演示代码来解码它:
use Compress::Zlib qw(uncompress);
use MIME::Base64 qw(decode_base64);
my $uncompresseddata = uncompress(decode_base64($compresseddata));
看起来很简单。
我尝试了多种方法来解码base64:
private string DecodeFromBase64(string encodedData)
{
byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
string returnValue = System.Text.Encoding.Unicode.GetString(encodedDataAsBytes);
return returnValue;
}
public string base64Decode(string data)
{
try
{
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch (Exception e)
{
throw new Exception("Error in base64Decode" + e.Message);
}
}
我尝试使用 Ionic.Zip.dll (DotNetZip?) 和 zlib.net 来增强 Zlib 压缩。但一切都出错了。我正在尝试找出问题出在哪里。是base64解码还是Inflate?
使用 zlib 膨胀时总是出现错误:使用 zlib.net 时出现错误的 Magic Number 错误,使用 DotNetZip 时出现“错误状态(无效的存储块长度)”:
string decoded = DecodeFromBase64(compresseddata);
string decompressed = UnZipStr(GetBytes(decoded));
public static string UnZipStr(byte[] input)
{
using (MemoryStream inputStream = new MemoryStream(input))
{
using (Ionic.Zlib.DeflateStream zip =
new Ionic.Zlib.DeflateStream(inputStream, Ionic.Zlib.CompressionMode.Decompress))
{
using (StreamReader reader =
new StreamReader(zip, System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
读完本文后: http://george.chiramattel.com/blog/2007/09/deflatestream-block-length-does-not-match.html 并听取其中一条评论。我将代码更改为:
MemoryStream memStream = new MemoryStream(Convert.FromBase64String(compresseddata));
memStream.ReadByte();
memStream.ReadByte();
DeflateStream deflate = new DeflateStream(memStream, CompressionMode.Decompress);
string doc = new StreamReader(deflate, System.Text.Encoding.UTF8).ReadToEnd();
并且运行良好。
这就是罪魁祸首:
http://george.chiramattel.com/blog/2007/09/deflatestream-block-length-does-not-match.html
通过跳过前两个字节,我可以将其简化为:
MemoryStream memStream = new MemoryStream(Convert.FromBase64String(compresseddata));
memStream.ReadByte();
memStream.ReadByte();
DeflateStream deflate = new DeflateStream(memStream, CompressionMode.Decompress);
string doc = new StreamReader(deflate, System.Text.Encoding.UTF8).ReadToEnd();
首先,使用
System.IO.Compression.DeflateStream
重新膨胀数据。您应该能够使用 MemoryStream
作为输入流。您可以使用 byte[]
的 Convert.FromBase64String
结果创建 MemoryStream。
尝试将 Base64 结果转换为给定编码时,您可能会遇到各种麻烦;直接使用原始数据进行Deflate。
使用 SharpZipLib 库 (https://www.nuget.org/packages/SharpZipLib),这可以解码/解压缩来自 Oracle/PeopleSoft 的 Content-Encoding: base64(deflate):
string base64String = File.ReadAllText(@"C:\base64.txt");
var decodedBytes = Convert.FromBase64String(base64String);
var uncompressedBytes = ZlibStream.UncompressBuffer(decodedBytes);
string result = Encoding.UTF8.GetString(uncompressedBytes);
File.WriteAllText(ResultPath, result);