我有一個討厭的問題,gzipstream瞄準.net 3.5。這是我第一次使用gzipstream,但是我已經模仿了很多教程,其中包括here,我仍然陷入困境。GZipStream - 即使使用flush也不寫所有壓縮數據?
我的應用程序將數據表序列化爲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機制解壓縮數據時,我只能獲得部分原始數據。
我開始賞金,但我真的沒有太多的聲譽,得到的現在:-(
重大事件。我會做出調整,看看它是如何發展的。 – longofest
所以,這顯然是一個問題,但不是這個問題...現在用最新代碼更新原始問題,但仍然得到0解壓縮讀取。 – longofest
...但我有幾次,我用緩衝區,而不是toarray ...嗯...讓我工作更多... – longofest