|
I am successfully using .NET's BinaryFormatter to serialize a very complex object (an instance, at run-time) into a MemoryStream, and I can save that to a file, and then de-serialize the file back into an instance of the object.
Then, I wanted to add compressing the MemoryStream using GZip [1], before saving it to a file.
I am, without compile- or run- time error, using .NET's GZip facility to GZip the created MemoryStream, and then save it to a disk file.
To summarize the save-to-file sequence:
1. use BinaryFormatter to serialize the object to a MemoryStream
2. use GZip to compress the MemoryStream
3. write the Gzipped MemoryStream to disk
I've already learned the hard way that there is a quirk in using GZip in .NET in compressing [^].
I verify that the file is written, and it appears to have been "shrunk" by the GZip facility.
But, when I try to reverse the process, to essentially deserialize (recreate) the object by:
1. reading the Gzipped saved file into a MemoryStream
2. using GZip's Decompress on the MemoryStream
3. using BinaryFormatter to deserialize the MemoryStream, which I then cast into the Type of the original object: fail.
The point I am stuck at is expressed in this code:
using (GZipStream deCompressionStream = new GZipStream(new MemoryStream(), CompressionMode.Decompress))
{
deCompressionStream.CopyTo(newMemoryStream);
}
BinaryFormatter bFormatter = new BinaryFormatter();
object obj = bFormatter.Deserialize(newMemoryStream); Thanks in advance for any advice.
yours, Bill
[1] I set out to explore using GZip as a way to increase my general knowledge of .NET's stream facilities, and after learning how to successfully use Mehdi Gholam's fastBinaryJSON work here on CP, and using the MiniLZO class in Mehdi's Raptor Document Store.
“Human beings do not live in the objective world alone, nor alone in the world of social activity as ordinarily understood, but are very much at the mercy of the particular language which has become the medium of expression for their society. It is quite an illusion to imagine that one adjusts to reality essentially without the use of language and that language is merely an incidental means of solving specific problems of communication or reflection." Edward Sapir, 1929
|
|
|
|
|
You're passing an empty MemoryStream to the GZipStream s constructor. You need to pass the stream containing the previously compressed data instead.
using (var fileStream = File.OpenRead(@"Path\To\Your\File.bin"))
using (var deCompressionStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
var bFormatter = new BinaryFormatter();
object obj = bFormatter.Deserialize(deCompressionStream);
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard, thanks very much for your example !
Your deserialization code is one of the first variations I tried, and it fails to deserialize with an error: "The magic number in GZip header is not correct. Make sure you are passing in a GZip stream."
Clearly my Gzipping is not being done properly. This is confirmed by this experiement: if I modify your code like this:
using (var fileStream = File.OpenRead(filePath))
using (var deCompressionStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
var bFormatter = new BinaryFormatter();
object obj = bFormatter.Deserialize(fileStream);
return null;
} That confirms to me I did not GZip properly.
I tried several variations of GZipping found on MSDN, and StackOverFlow: almost all these examples use source.CopyTo(destination) in some form, within the using statements bracketing the use of GZipStream, evidently for the reason there is a known problem with GZipping not being completed fully until after it exits the 'using statement closure, as referenced here: [^].
So, the burden shifts back to finding the correct way for Gzipping.
thanks again for your time, Bill
|
|
|
|
|
You're copying streams which isn't required; they're based on the decorator-pattern. Below example should work (albeit the GZipped version will be bigger since it's a small class)
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.IO.Compression;
[Serializable()]
class SumTestClass
{
public int TestInt { get; set; }
public string TestString { get; set; }
public SumTestClass()
{
TestInt = 42;
TestString = "Hello World";
}
}
static class Program
{
static BinaryFormatter bf = new BinaryFormatter();
static void Main(string[] args)
{
object thingyToSerialize = new SumTestClass();
using (var ms = new FileStream("C:\\Temp\\Test.zip", FileMode.Create))
using (var zs = new GZipStream(ms, CompressionMode.Compress, leaveOpen: true))
{
bf.Serialize(zs, thingyToSerialize);
Console.WriteLine("Stuff saved");
}
using (var ms = new FileStream("C:\\Temp\\Test.zip", FileMode.Open))
using (var zs = new GZipStream(ms, CompressionMode.Decompress, leaveOpen: true))
{
SumTestClass testResult = bf.Deserialize(zs) as SumTestClass;
Console.WriteLine("String: {0}\nInt: {1}", testResult.TestString, testResult.TestInt);
}
Console.ReadLine();
}
} Hope it helps a bit, yell if it doesn't
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Thanks, Eddy !
Your code works with a MemoryStream that has been Gzipped, Serialized, and written to a file.
The 'leaveopen parameter ... in both gzip, and un-gzip ... appears to be redundant: my implementation of your code works with, or without, them.
It compresses a 9mb object=>source-stream to a little over 3mb disk file, whether Compression setting is 'Fastest, or 'Optimal.
"Raising the stakes" from 100k to 1 million total objects yielded a 98+ megabyte MemoryStream that Gzipped to a 30.6mb file with both 'Optimal, and 'Fastest compression. That does make me question the efficiency of Gzip in .NET.
But (hypothesis), perhaps the complex object I am Gzipping and Serializing is, by its nature not highly compressible ?
It is much better to have working code you don't quite understand, than to have code you believe you understand, and expect to work, that does not work
When I feel like I fully understand how I "strayed onto the wrong path" for so many hours, yesterday, and understand exactly why your code works, I feel I should write up a Tip-Trick for CP.
I didn't realize that by using a ".gz" extension to the files I created I was creating something that could be opened with WinRar !
yours, Bill
~
"This isn't right. This isn't even wrong." Wolfgang Pauli"
|
|
|
|
|
You're welcome
BillWoodruff wrote: "Raising the stakes" from 100k to 1 million total objects yielded a 98+ megabyte MemoryStream that Gzipped to a 30.6mb file with both 'Optimal, and 'Fastest compression. That does make me question the efficiency of Gzip in .NET. Alternatively, one could launch an external process and wait for the command to finish. And suddenly, one can easily switch out the ZIP and try an ARJ, or a LHArc
BillWoodruff wrote: I feel I should write up a Tip-Trick for CP. Please do
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Eddy Vluggen wrote: Alternatively, one could launch an external process and wait forthe command to finish. And suddenly, one can easily switch out the ZIP and try an ARJ, or a LHArc I have thought about experimenting with launching something like 7-Zip via Process.Start, as suggested (but never detailed) on the 7-Zip discussion forums, but I wonder if, in using any externally launched process, the (possibly required) transfer of the stream to be compressed, or the creation of a "temp" file to hold the stream, before invoking the external process' facilities, would add an "overhead" that would negate its benefit.
I have SharpCompress, found here on CodeProject [^], working, but am not seeing any radical improvement in the current test case over .NET's built-in GZip.
Yesterday I spent a few hours trying to get SharpZipLib [^] working in VS 2012, FrameWork 4.5, without success. But, I'll try that again today.
thanks, again, Bill
~
“This isn't right; this isn't even wrong." Wolfgang Pauli, commenting on a physics paper submitted for a journal
modified 19-Jul-13 1:10am.
|
|
|
|
|
BillWoodruff wrote: would add an "overhead" that would negate its benefit. To answer that, one needs to investigate both overhead and benefit. Yes, it does introduce a slight overhead - but not very much if you hide the console-window. Consider it an isolated, switchable, heavyweight instance of a thread.
BillWoodruff wrote: SharpCompress, SharpZipLib Let's also add DotNetZip[^]. And LZMA[^].
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
See http://www.virtualdub.org/blog/pivot/entry.php?id=335[^] for how much it sucks.
There are various 3rd party deflate libs that suck less, I recommend SharpZipLib (nice license, too).
Though personally I recommend not using the built-in serialization in the first place and just dumping your raw data in a stream. It's a little more work up-front, but it's more flexible, a lot faster, and your data format will actually make sense (which is not always important of course). You can still put it through Deflate of course, I tend to do that (easier than explicitly storing sparse arrays and such).
|
|
|
|
|
That's an excellent analysis of GZip's limitations, in the article you cite, on virtualdub.com !
As I just commented to Eddy (post above): "Yesterday I spent a few hours trying to get SharpZipLib working in VS 2012, FrameWork 4.5, without success. But, I'll try that again today."
thanks, Bill
~
“This isn't right; this isn't even wrong." Wolfgang Pauli, commenting on a physics paper submitted for a journal
|
|
|
|
|
GZip Stream writes information to the stream after it is "closed" when creating the compressed zip stream. Do not wrap your compression in the using block. Call flush before closing out the stream when compressing. Then your decompress code may work.
|
|
|
|
|
Thanks, Ennis, I was aware of that issue, and in the OP, I cited a response on StackOverFlow:
"I've already learned the hard way that there is a quirk in using GZip in .NET in compressing [^]:"
That post cites a Microsoft BCL blog: [^].
yours, Bill
“This isn't right. This isn't even wrong." Wolfgang Pauli
|
|
|
|
|
How can I select flash textbox, past text, and click button in C# WebBrowser?
TextBox and Button: s7.postimg.org/oh2w84js7/button.jpg
Form where button is:
<form name="working" action="object_do.php" method="POST"><br><table class="wb" width="100%"><tbody><tr><td class="wbwhite" align="center" colspan="2">blahblahblah</td></tr><tr><td class="wb" width="140"><img src="work_codes/15903-34/1701507--381682.jpeg" width="250" height="60" border="0" name="imgcode"></td><td class="wblight" valign="center" width="100%"> <input type="hidden" size="4" name="code" autocomplete="off"><input type="hidden" value="5" name="id"><input type="hidden" value="5" name="id2"><script type="text/javascript">swfobject.registerObject("2e7f13a242369aa0a133ee3dced5bf5d", "9.0.0", "http://***/swffiles/expressInstall.swf");</script>
<div>
<object id="2e7f13a242369aa0a133ee3dced5bf5d" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="147" height="22" style="visibility: visible;">
<param name="movie" value="swffiles/459017015079176508wworkcode.swf?ver=1701507bf3d40fb076319ff7e6c2fc7a4898acdd88">
<param name="FlashVars" value="params=1701507|5|f3d40fb076319ff7e6c2fc7a4898acdd|">
<param name="bgcolor" value="#f5f3ea">
<param name="allowScriptAccess" value="always"><param name="wmode" value="opaque"><!--
BUTTON AND TEXT BOX-----------> <object type="application/x-shockwave-flash" data="swffiles/459017015079176508wworkcode.swf?ver=1701507bf3d40fb076319ff7e6c2fc7a4898acdd88" width="147" height="22">
<param name="FlashVars" value="params=1701507|5|f3d40fb076319ff7e6c2fc7a4898acdd|">
<param name="bgcolor" value="#f5f3ea">
<param name="allowScriptAccess" value="always"><param name="wmode" value="opaque"><!--
<div>
<p><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"></a></p>
</div>
<!--
</object>
<!--
</object>
</div></td></tr><tr><td class="wblight" colspan="2"><br> blahblahblah "blah".</td></tr></tbody></table></form>
|
|
|
|
|
it is inconceivable copying from flash file because it is compiled and how you want do that?
it's my opinion
-Amir Mohammad Nasrollahi
/* LIFE RUNS ON CODE */
|
|
|
|
|
|
I fail to understand the reason behind that requirement. Adobe Acrobat reader is available for many browsers (perhaps no more supporting extremely outdated legacy browsers like IE6 or NetScape 4) on many platforms - even Linux. And most browsers are already configured to use that. Why do you insist on soemthing different?
|
|
|
|
|
good
/* LIFE RUNS ON CODE */
|
|
|
|
|
as what "Bernhard Hiller" says adobe acrobat is free and suported by many browsers but from your selections list, verypdf can be better because of prices and good support (tasted by one of my friends)
/* LIFE RUNS ON CODE */
|
|
|
|
|
Hi,
i face a problem to create a setup of window application in vs2010.
for create a setup i use vs window installer and done step by step as i seen many examples in Google( how to create setup for window application).
But in my case shortcut create in desktop, but when i click on the shortcut it will running look like as it install project again.
same uninstall project create in all programs but when i click on them nothing happens.
please help me.
Thanks.
|
|
|
|
|
Create shortcut of executable by right click on it in Application Folder in “File System” Section of Setup Project. And then cut the shortcut of file and paste it into user desktop folder and build the project.
It should work.
|
|
|
|
|
Hello All,
I was wanting to start a discussion about best practice when creating threads in a Windows Service.
I have a service that has multiple process running at the same time (6-10). Is it better to use timers or threads? I personally prefer threads because I can end them all with a single line of code where as if have to end each timer individually. Plus with threads, you don't have to worry about it calling it self until you want it to.
Does anybody have any other thoughts on this? What's a better way to go and why? Which is lighter on PC usage and memory? etc etc
Thanks in advance,
Bryan
|
|
|
|
|
BBatts wrote: Is it better to use timers or threads?
When the timer fires it uses a thread.
BBatts wrote: Plus with threads, you don't have to worry about it calling it self until you
want it to.
Huh? If the thread is running and not blocked then it is fact running. If you weren't saying that I am not sure what you are saying because the execution flow is always in one thread or another.
BBatts wrote: because I can end them all with a single line of code
Not sure what that means exactly. At least sometimes one can't just end threads arbitrarily and sometimes one must end them in a certain order. But the same applies to timers but only to the extent that they too are using threads.
|
|
|
|
|
"When the timer fires it uses a thread."
Yes. To be more specific a timer is an object the fires a thread periodically.
"Huh? If the thread is running and not blocked then it is fact running"
If the thread your timer has fired takes longer to execute than the interval level of a timer it will fire again. Unless, of course, you disable it. Where as if one is using a System.Thread there is more direct control over when and how the thread is fired.
I can't think of any reason to use a Timer as opposed to System.Thread...in a windows service. I guess that was the point of my post.
|
|
|
|
|
BBatts wrote: System.Thread there is more direct control over when and how the thread is
fired.
How exactly do you "fire" a thread in the above?
How exactly do you think that process is different than what a timer does?
BBatts wrote: I can't think of any reason to use a Timer as opposed to System.Thread...in a
windows service
Because one wants an action to occur based on something associated with time. For example running a process every hour or once a day.
|
|
|
|
|
You are not comparing like with like: timers have one purpose, threads another.
Use the best guess
|
|
|
|
|