我正在使用GZipStream
压缩字符串,我修改了两个不同的示例以查看哪些有效。第一个代码片段是the example in the documentation的重度修改版本,只返回一个空字符串。
public static String CompressStringGzip(String uncompressed)
{
String compressedString;
// Convert the uncompressed source string to a stream stored in memory
// and create the MemoryStream that will hold the compressed string
using (MemoryStream inStream = new MemoryStream(Encoding.Unicode.GetBytes(uncompressed)),
outStream = new MemoryStream())
{
using (GZipStream compress = new GZipStream(outStream, CompressionMode.Compress))
{
inStream.CopyTo(compress);
StreamReader reader = new StreamReader(outStream);
compressedString = reader.ReadToEnd();
}
}
return compressedString;
当我调试它时,我只能从reader
读取所有内容,compressedString
为空。但是,我写的第二种方法,从CodeProject snippet修改成功。
public static String CompressStringGzip3(String uncompressed)
{
//Transform string to byte array
String compressedString;
byte[] uncompressedByteArray = Encoding.Unicode.GetBytes(uncompressed);
using (MemoryStream outStream = new MemoryStream())
{
using (GZipStream compress = new GZipStream(outStream, CompressionMode.Compress))
{
compress.Write(uncompressedByteArray, 0, uncompressedByteArray.Length);
compress.Close();
}
byte[] compressedByteArray = outStream.ToArray();
StringBuilder compressedStringBuilder = new StringBuilder(compressedByteArray.Length);
foreach (byte b in compressedByteArray)
compressedStringBuilder.Append((char)b);
compressedString = compressedStringBuilder.ToString();
}
return compressedString;
}
为什么第一个代码段不成功而另一个代码片段不成功?尽管它们略有不同,但我不知道为什么第二个片段中的微小变化允许它起作用。我正在使用的示例字符串是SELECT * FROM foods f WHERE f.name = 'chicken';
答案 0 :(得分:2)
我最终使用以下代码进行压缩和解压缩:
public static String Compress(String decompressed)
{
byte[] data = Encoding.UTF8.GetBytes(decompressed);
using (var input = new MemoryStream(data))
using (var output = new MemoryStream())
{
using (var gzip = new GZipStream(output, CompressionMode.Compress, true))
{
input.CopyTo(gzip);
}
return Convert.ToBase64String(output.ToArray());
}
}
public static String Decompress(String compressed)
{
byte[] data = Convert.FromBase64String(compressed);
using (MemoryStream input = new MemoryStream(data))
using (GZipStream gzip = new GZipStream(input, CompressionMode.Decompress))
using (MemoryStream output = new MemoryStream())
{
gzip.CopyTo(output);
StringBuilder sb = new StringBuilder();
return Encoding.UTF8.GetString(output.ToArray());
}
}
部分问题的解释来自this question。虽然我通过将代码更改为我在此答案中包含的内容来解决问题,但这些行(在我的原始代码中):
foreach (byte b in compressedByteArray)
compressedStringBuilder.Append((char)b);
是有问题的,因为dlev适当地表达了它:
您将每个字节解释为自己的字符,而事实并非如此。相反,你需要这一行:
string decoded = Encoding.Unicode.GetString(compressedByteArray);
基本问题是您正在转换为基于编码的字节数组,但在检索字节时忽略该编码。
因此,问题解决了,我使用的新代码比原始代码简洁得多。
答案 1 :(得分:0)
您需要将下面的代码移到第二个使用语句之外:
using (GZipStream compress = new GZipStream(outStream, CompressionMode.Compress))
{
inStream.CopyTo(compress);
outStream.Position = 0;
StreamReader reader = new StreamReader(outStream);
compressedString = reader.ReadToEnd();
}
CopyTo()没有将结果刷新到底层的MemoryStream。
<强>更新强>
似乎GZipStream在处理时关闭并处理它的底层流(不是我设计类的方式)。我已经更新了上面的示例并进行了测试。