gpt4 book ai didi

c# - GZipStream - 即使刷新也不写入所有压缩数据?

转载 作者:太空狗 更新时间:2023-10-29 22:13:46 27 4
gpt4 key购买 nike

我遇到了一个针对 .Net 3.5 的 gzipstream 的讨厌问题。这是我第一次使用 gzipstream,但是我已经模仿了许多教程,包括 here我仍然卡住了。

我的应用程序将数据表序列化为 xml 并插入数据库,将压缩数据存储到 varbinary(max) 字段以及未压缩缓冲区的原始长度。然后,当我需要它时,我检索这些数据并将其解压缩并重新创建数据表。解压缩似乎失败了。

编辑:遗憾的是,按照建议将 GetBuffer 更改为 ToArray 后,我的问题仍然存在。代码更新如下

压缩代码:

DataTable dt = new DataTable("MyUnit");
//do stuff with dt
//okay... now compress the table
using (MemoryStream xmlstream = new MemoryStream())
{
//instead of stream, use xmlwriter?
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
settings.Encoding = Encoding.GetEncoding(1252);
settings.Indent = false;
System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(xmlstream, settings);
try
{
dt.WriteXml(writer);
writer.Flush();
}
catch (ArgumentException)
{
//likely an encoding issue... okay, base64 encode it
var base64 = Convert.ToBase64String(xmlstream.ToArray());
xmlstream.Write(Encoding.GetEncoding(1252).GetBytes(base64), 0, Encoding.GetEncoding(1252).GetBytes(base64).Length);
}

using (MemoryStream zipstream = new MemoryStream())
{
GZipStream zip = new GZipStream(zipstream, CompressionMode.Compress);
log.DebugFormat("Compressing commands...");
zip.Write(xmlstream.GetBuffer(), 0, xmlstream.ToArray().Length);
zip.Flush();
float ratio = (float)zipstream.ToArray().Length / (float)xmlstream.ToArray().Length;
log.InfoFormat("Resulting compressed size is {0:P2} of original", ratio);

using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "INSERT INTO tinydup (lastid, command, compressedlength) VALUES (@lastid,@compressed,@length)";
cmd.Connection = db;
cmd.Parameters.Add("@lastid", SqlDbType.Int).Value = lastid;
cmd.Parameters.Add("@compressed", SqlDbType.VarBinary).Value = zipstream.ToArray();
cmd.Parameters.Add("@length", SqlDbType.Int).Value = xmlstream.ToArray().Length;
cmd.ExecuteNonQuery();

}
}

解压代码:

/* This is an encapsulation of what I get from the database
public class DupUnit{
public uint lastid;
public uint complength;
public byte[] compressed;
}*/
//I have already retrieved my list of work to do from the database in a List<Dupunit> dupunits
foreach (DupUnit unit in dupunits)
{
DataSet ds = new DataSet();
//DataTable dt = new DataTable();
//uncompress and extract to original datatable
try
{
using (MemoryStream zipstream = new MemoryStream(unit.compressed))
{
GZipStream zip = new GZipStream(zipstream, CompressionMode.Decompress);
byte[] xmlbits = new byte[unit.complength];
//WHY ARE YOU ALWAYS 0!!!!!!!!
int bytesdecompressed = zip.Read(xmlbits, 0, unit.compressed.Length);
MemoryStream xmlstream = new MemoryStream(xmlbits);
log.DebugFormat("Uncompressed XML against {0} is: {1}", m_source.DSN, Encoding.GetEncoding(1252).GetString(xmlstream.ToArray()));
try{
ds.ReadXml(xmlstream);
}catch(Exception)
{
//it may have been base64 encoded... decode first.
ds.ReadXml(Encoding.GetEncoding(1254).GetString(
Convert.FromBase64String(
Encoding.GetEncoding(1254).GetString(xmlstream.ToArray())))
);
}
xmlstream.Dispose();
}
}
catch (Exception e)
{
log.Error(e);
Thread.Sleep(1000);//sleep a sec!
continue;
}

注意上面的评论...bytesdecompressed 始终为 0。有什么想法吗?我做错了吗?

编辑 2:

所以这很奇怪。我在解压例程中添加了以下调试代码:

   GZipStream zip = new GZipStream(zipstream, CompressionMode.Decompress);
byte[] xmlbits = new byte[unit.complength];
int offset = 0;
while (zip.CanRead && offset < xmlbits.Length)
{
while (zip.Read(xmlbits, offset, 1) == 0) ;
offset++;
}

调试时,有时该循环会完成,但有时会挂起。当我停止调试时,它将位于 1616 字节中的第 1600 字节。我会继续,但它根本不会移动。

编辑 3: 该错误似乎出现在压缩代码中。无论出于何种原因,它都没有保存所有数据。当我尝试使用第三方 gzip 机制解压缩数据时,我只得到了部分原始数据。

我会开始赏金,但我现在真的没有多少声望可以给予 :-(

最佳答案

终于找到答案了。压缩数据不完整,因为 GZipStream.Flush() 完全没有做任何事情来确保所有数据都在缓冲区之外 - 您需要使用 GZipStream.Close() 作为 pointed out here .当然,如果压缩不好,一切都会变得糟糕 - 如果您尝试解压缩它,Read() 将始终返回 0。

关于c# - GZipStream - 即使刷新也不写入所有压缩数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24512675/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com