Summary
I’ll create a file(s) zipper/unzipper in this tutorial. You suggestions are welcome to make the idea (or this application) better.




Background
The idea came from a post I answered few days back. The post is here — http://forum.codecal…ges-to-streams/. The problem was that, the poster wanted to write images as well as other things like text, number etc in a binary stream. He also wanted to get the data back as separate items he wrote. So the problem is a general one — writing multiple files in a stream and retrieving the files from that stream. The BinraryWriter & BinaryReader classes are there for the job. In BinaryWriter class there is Write method with various overloaded version which takes bool, String, numbers etc as the parameter and we can get back the same data with ReadBoolean, ReadInt, ReadString, ReadDouble methods of BindaryReader class. Perhaps you noticed that there is a single method – Write – for writing everything but multiple methods for reading. Yeah, this is because we can pass multiple arguments in a method but a method can only returns one. There is an overloaded of Write method which takes byte[] type parameter. So while reading you can use ReadBytes method of BinaryReader but you need to specify/know how many bytes you want to read. In case of ReadInt, ReadDouble, ReadString the BinaryReader knows the length of bytes need to read from the stream, but you need to specify the amount of bytes you want to read while using ReadBytes method. So the solution I gave him was simple — write the number of bytes you are writing before writing the bytes itself. I follow the same protocol/logic while I send/receive data in case of networking applications. I guess the BinaryWriter does the same thing while we call Write method with various parameters (except the byte[]) — that is while we call Write with int type, it first write 4 (size for int) in a byte onto the stream followed by writing the actual 4 bytes data we passed. Same thing for other types as well as String — except the byte[]. I think that is possible to do the same thing in case of byte[] but I don’t why they didn’t.

However, after answering on the post, I decided to write a files merger/demerger. After finishing the app (just merge files into a single one and in reverse, demerge the file into the files it was merge from), I decided to go a bit farther. I decided to make a zipper/unzipper application using some opensource tools which will do the compressing/decompressing of data. And thus, this tutorial got its way to find out a place in CodeCall (as well as a demo app). However, there is still a thing left to do and I’ll tell about it when that point will come up.


The Protocol
The protocol I’ll follow while writing and reading to/from the singled merged file is as follows…
If the item is a folder, we will not write the last two parts.


The Merging/Demerging of Files
The code that will merge the files into a single one is as follows. While merging, it will also update on GUI (in a grid view)

The code that will demerge the files from a single one is as follows. While demerging, it will also update on GUI (in a grid view)…


The Compression/Decompression of Content of File
Though the first idea was to just create a merger/demerger, later I decided to use some code to add the compression/decompression part. I used the 7zip LZMA SDK to perform this part. It is free and opensource. Please read more about it here — http://www.7-zip.org/sdk.html. I was looking for method which will take some bytes and returns some bytes after compression/decompression. I made something like it (with the help of Google) using the default parameters for the corresponding methods from the SDK. I found something like following…


The File Association with FileSystem
Though I desired to do everything from file system like WinRAR but I’m not. Well, there are two parts —

  • I need to associate an extention (.kcl) to this app. I’m able to do that. It just adding the extension under HKEY_CLASSES_ROOT registry (with DefaultIcon and command keys). So when a file with kcl extension will get double clicked (or open by right clicking), this app will get called (see the command key’s value) with the file as argument.
  • Adding a context menu for every types of file and folder. Well, its easy, you just need to add an entry for ‘*’, ‘Directory’ & ‘Folder’ keys of HKEY_CLASSES_ROOT.


I used the above two methods to make the association (as well as deleting the association) of the extensions (kcl, *, Folder, Directory) with our application. The ‘Install‘ method will get called if we pass ‘-i’ switch to the app. The ‘Uninstall‘ method will get called if we pass ‘-u’ switch to the app.


Now, the problem I’m facing with the association is that if I click multiple files/folder and click on the “Archive with KCL Zipper” menu, it calls the application for each of the file and folder (I mean each instance of application is running for each file/folder). But I want it to get only one instance of the application. I tried to find out a solution to this — but no hope so far. Actually, I’m looking for a registry tweaking way so that the explorer/shell will do that for me – not able to find such a way so far. Another way can be — doing the trick from inside the application itself. I have to make the application singleinstance so when second or more instance will run, it will send file/folder name it got to the first application. I can do that but that will take a bit time. Besides I’m looking for some simple solution. Can you guys help on this?


Future Enhancements

  • Adding the necessary changes so that the compressed files generated by this app can be extracted by other applications like WinZIP and vice versa.
  • Making the application cross-platform with Qt/QML.


What Do You Think on This ? Say Here