ZipStream module
BlitzMax Forums/BlitzMax Programming/ZipStream module
| ||
This module adds two new stream protocols for zip support in streams : "zip" and "zip?" "zip" is for reading files that are in the specified zip. "zip?" is for reading files that are in the specified zip OR (if not found in the zip) on the hard drive (or any other location supported by streams). The zip stream works over another stream. This means that you can not only access zip files on the hard drive, but also zp files that are incbined, or even zip files within other zip files, and so on. Example of valid urls: "zip::myGame/myZip.zip//someFile.txt", or even "zip::incbin::myGame/myZip.zip//someFile.txt" if the zip file is incbined. So you could do by example: LoadText("zip::myGame/myZip.zip//someFile.txt") Use as you please. Grab it here (you need to be logged in the forum to see the download link): http://www.koriolis-fx.com/forum/index.php?topic=15.0 |
| ||
Seems it load directly into mem and won't generate temp file, nice. Thanks for the handy module |
| ||
MacOS and Linux compatible? |
| ||
Seems it load directly into mem and won't generate temp file, nice. Yes. That's the whole point, the zip stream works over another stream, making it very versatile, and letting you access a zipped file wherever it's stored. MacOS and Linux compatible? It's based solely on ZLib so it should definitely work on Mac and Linux. I just didn't bother to compile it on Mac or Linux yet. If anyone wants to compile it and check that it works OK for these platforms, I will happily include the resulting binaries. |
| ||
Thanks for the mod but I have a problem, maybe you can explain me where is the errorLocal te:tstream = OpenStream("zip::test_bmax.zip//test_zip.txt") If te While Not Eof(te) Print ReadLine(te) Wend CloseStream(te) Else Print "no stream found" End If Local testo:String=LoadText("zip::test_bmax.zip//test_zip.txt") Print "Text: "+testo I have created a .zip file (test_bmax.zip) that contains the file test_zip.txt. I have the error 'No stream found' (te=NULL) but LoadText() works perfectly. What I miss? |
| ||
Silly question, but did you actually import koriolis.zipstream? |
| ||
checking this one out now, sounds like it could definitely come in handy... |
| ||
If it support password it'll become killer. Can it add something like $zippass to specify password? |
| ||
Great module Koriolis !! Many thanks :) Good job :) |
| ||
Silly question, but did you actually import koriolis.zipstream? Of course, the second part of the program Local testo:String=LoadText("zip::test_bmax.zip//test_zip.txt") Print "Text: "+testo works perfectly: the 'zip::' protocol is recognized. but only for the LoadText command. |
| ||
"but only for the LoadText command" ??? I can't load an image from this zip ?? |
| ||
If FileType("zipped_image.zip") Print "File exists" End If Local zimage:timage = LoadImage("zip::zipped_image.zip/back_muro_2.png") If zimage Print "Image loaded" Else Print "Image NOT loaded" End If This is a test for loading an image from a file 'zipped_image.zip'. But - for me - it doesn't work. Can anyone else do some tests please? So only to understand if there is a problem with my configuration. |
| ||
If it support password it'll become killer. Yes it does. You can register a zip password globally, using SetZipStreamPasssword. Once done you can access the passworded file just like a unpassworded file.@degac: you need a double slash to separate the zip path from the file inside the zip. With Local zimage:timage = LoadImage("zip::zipped_image.zip/back_muro_2.png") youare trying to load the zip file "zipped_image.zip/back_muro_2.png" but you want to access the zip file "zipped_image.zip" and get the file "back_muro_2.png" inside of it. You need to do: Local zimage:timage = LoadImage("zip::zipped_image.zip//back_muro_2.png") But as said below there is another problem then. I can't load an image from this zip ?? I just tried with LoadPixmapPNG and it works. I then tried with LoadImage and apparently it doesn't work because the ZipStream is not seekable. Is that the error you get ? The problem is I don't know yet how to make the zip stream seekable, as I can't find any function in zlib that lets me do that. |
| ||
Perhaps you can try the loadimage(loadbank()) trick as when trying to loadimage from a http:: stream |
| ||
Well, actually I just made a simple fix: For the special case when Seek(0) or Seek( current pos ) is called, the seek now works. This is limited, but is enough to make LoadImage() work with the zip stream. Please redownload the module and let me know if you still encounter problems. |
| ||
What's the difference to GMan's Zip module? |
| ||
GMan's zip module provides everything you need to mainpulate zip files in pretty much every way you wish, BUT using a special dedicated API. On the contrary, the zipstream module let's you read zipped files using the standard TStream interface. This means that any piece of code that works on a TStream can work on zipped files. If you (or anyone) have written code that works on TStream, you don't have to write another version to handle zipped files: just use the "zip::" protocol and that's it. By example you can already use the standard functions LoadText and LoadImage with zipped files. |
| ||
Ok. New version works perfectly with LoadImage(zip::). Thank you very much! |
| ||
Thanks for the explanation. Btw: Gman's version can also extract data directly into the ram and read it from threre. |
| ||
Gman's version can also extract data directly into the ram and read it from threre. Yes, but it's still not a stream protocol, and perhaps more important it requires to extract the whole file into memory. On the other hand, my zip stream extracts data on the fly. I think both modules are very much complementary. By example I personnaly use GMan's zipengine to create zip files, and my zip stream to read it back (from another program). |
| ||
So your solution is faster in terms of extracting files? |
| ||
It should overall be a bit faster, yes. To be clear, the raw extraction is probably slower, but there is no need for a second pass (reading from memory). More important, there is no need for a block of memory as big as the file itself. |
| ||
thx, this works great, is very fast too, have used it today just to test storing images and loading, very good. only issue i have is with passwords: Graphics 640,480; SetZipStreamPasssword("test.zip","gavsta") Global testimg:timage =LoadImage("zip::test.zip//untitled-1.jpg"); While Not KeyHit(KEY_ESCAPE) Cls DrawImage(testimg,0,0) Flip Wend this always comes back with "Attempt to Access field or method of Null Object". if i turn off the password side it works fine? **EDIT** just ignore me, i'm having one of those days, would help if i had called the file test.zip and not test.zips |
| ||
Question: is it possible to *combine* two methods like incbin and zipstream, to add another layer of protection? (e.g. resources inside of password-protected incbinned ZIP) |
| ||
Here is an example with incbinned zip :) Nice module ! really usefull ! |
| ||
Glad you like it :) |
| ||
As a temporary fix could you use replace the seek method with one that goes to the beginning and reads the offset number of bytes? |
| ||
I'll check that, *maybe* this week end. If I forget, remind me. I had already thought of doing it that way, I just didn't bother. Howerver, to avoid being totally inefficient I'd need to make the stream buffered (or else, if it happens that you do something like seeking to N, N+1, N+2 etc, then it will totally ineffieicnt as for every single byte it will restart from the beginning). |
| ||
Wicked, This is just what I need, If this can decompress Incbin'd Zips straight to RAM (Not Temp HDD file) I dont have time to try this out right now but im definitely interested in using this in my software Long Live BlitzMax and its Modules |
| ||
it does'nt work: i get "Stream is not seekable" |
| ||
i've found that the zipstream does'nt work with pantsons MPEG module: Local movie:Tmpeg = OpenMPEG("zip::intro.zip//intro.ogg") |
| ||
Yes, as stated earlier the stream is not seekable (yet) except for 2 special cases. I will do my best to fix that when I have time. |
| ||
i've found that the zipstream does'nt work with pantsons MPEG module: Is there even any benefit doing so? zip compression is negligible on an MPEG file, and I'd think that the added overhead of unzipping it would outweigh the minor size savings... |
| ||
Is there a command for counting the total files inside a zip file? |
| ||
Wow, really handy! :) Thanks for sharing such a great mod free! ;) Dabz |
| ||
Very handy tool! Really like the way it integrates into the commands. degac: I have created a .zip file (test_bmax.zip) that contains the file test_zip.txt. I have the error 'No stream found' (te=NULL) but LoadText() works perfectly. What I miss? I played with this because I need it too. I found I can open the stream with: Local te:tstream = OpenStream("zip::test_bmax.zip//test_zip.txt", true, false) where false tells it the file is NOT writable. Hope that helps. Silly question: (I really new to posting) How do you format text in the reply window and add things like the scrolling text box? |
| ||
This is perfectly normal, the stream is read only. The intent is really to use zip files as in Quake by example : as big "pak" data files. For *writing* into the stream, either simply create the zip files using Winzip or whatever, or use GMan's ZipEngine module. Thus you should not try to open the stream in write mode. ReadStream(...) will work, as well as OpenStream(..., ..., false). But WriteStream(...) or OpenStream(..., ..., true) won't. |
| ||
I've run into a problem. I can open text files, image files, and font files in the zip with no problem, but when sound is introduced into the game (not in the zip, just using standard files) I get "Attempt to Access field or method of Null Object" from weird places in my code and the standard editor bombs if I try to access the debug info. If I take out the zip:: references the code runs clean. Any ideas? |
| ||
Most probably, you tried to load the sound file using the ZipStream, the loading failed, you didn't check that the load was successfull or not and tried to play that Null audio sample. As mentioned earlier, there is still an issue : the stream is not seekable. I will look at the the issue when I have more time. So if you load a sound file that is loaded using TStream.Seek, then it won't work. I tried with Wav files and it works, but it all depends on the file format you're loading, and the way the loading code is written. |
| ||
Most probably, you tried to load the sound file using the ZipStream, the loading failed, you didn't check that the load was successfull or not and tried to play that Null audio sample. workaround? loadsound(loadbank("zip::mysound.zip//sound.ogg")) |
| ||
yes, this is the logical workaround, and will always work. However I can't pretend it wouldn't be better to have it work without this workaround. I *will* try to fix this, I just don't know when. |
| ||
I have finally fixed the limitation concerning TZipStream : it is now entirely seekable. By example I can now load zipped ogg files (which require the stream to be seekable), it works perfectly (don't tell me zipping ogg files is stupid, it's just a test, and actually CAN make sense). You can download the new version at the same place. |
| ||
Hi I'm testing your last zipstream module, but I have 'Stream is not seekable' when I try to load a .ogg file. I also have used the 'buf::' protocol, without success. Only with CreateBufferedStream() function it works. (I'm using Import koriolis.bufferedstream) Can you post a working example? Thanks again |
| ||
Working example:Import koriolis.zipstream Local sound:TSound = LoadSound("zip::D:\BlitzMax\samples\digesteroids\sounds\menu.zip//menu.ogg") PlaySound(sound) While Not KeyHit(1) Wend For your problem, it's likely that you're still using the old version. One reason might be that the zip files containing the modules will be extracted to zipstream.mod/zipstreamkoriolis.mod and bufferedstream.mod/bufferedstream.mod. But in the BlitzMax "mod" folder, you must have mod/koriolis.mod/zipstream.mod and mod/koriolis.mod/bufferedstream.mod. So be carefull to copy the zip content at the right place. |
| ||
Hi. This module is great but I'm not getting the password feature. Is it only meant for incbinned zip folders? Is it supposed to actually set a password for a zip folder? I can set a password then exit the program and open the zip folder normally using no password. EDIT: Nm I got it. Create your zip folder. Click file->add password. Awesome! |
| ||
Just few words to say that i'm using your module all the time! :) Thanks Koriolis for this great piece of code :) |
| ||
Thans for the thanks :) |
| ||
Koriolis: this is an awesome module! Thank you so much for sharing it. Now I must ask: any possibility of getting zip writing added? This would make for a great save game function when there are many files generated: throw them all into a zip file to keep them organized, and then password lock it to prevent hacking! Either way, thanks again for sharing! |
| ||
It is certainly doable, however I do no have much time for this. In addition I believe write support is much less important here, and if you really need it I highly recommend using the ZipEngine module from GMan. If anyone feels like adding write support, I will happily test that and incorporate it in the module. |
| ||
An excellent addition, thanks for sharing the code. For those wanting to use a subfolder witin the ZIP file replace your "\" with "/" before you open the file. filename = filename.Replace("\", "/") |
| ||
Hi Koriolis : Any chances to get it work with blitz3D Sdk ? |
| ||
Not much. The module is totally dependant on BlitzMax streams. blitz3D Sdk is just an SDK, I don't believe they have included any kind of general stream system in it. Now let's imagine you add a general stream framework on top of blitz3D Sdk, or use an existing one (say C++ stl streams if you're using C++) it will be mostly worthless as the SDK itself won't be using it and thus you have zero chance of having the sdk load a model from yor zip. Plus I don't own blitz3D Sdk and have no interest in it. The only possibility would be if you're using BlitzMax AND the BlitzMax version of blitz3D Sdk is based on BlitzMax streams (which basically requires that the sdk is written in BlitzMax). In this case, the zipstream module should work out of the box with the sdk. |
| ||
Ok thanks :) |
| ||
Is there a way to detect if a file stored inside a zip is present at all? |
| ||
What happens when you try to read a file from the zip that does not exist? |
| ||
What happens when you try to read a file from the zip that does not exist? I'm itching to say.. :PGrisu: If you try to open a stream to a zip path (or any path, for that matter), and it does not exist, your stream should be Null. |
| ||
Well, the app crashes completely which is not good. I did check for the null stream but it doesn't help here. ;) @Brucey: See (TuneIn_Station)line: Local zstation:String = LoadText("zip::"+fullzipdir) Probably it's the loadtext function that has no fail check?! :D |
| ||
Probably it's the loadtext function that has no fail check From memory... LoadText used to crash if given a Null filename - don't know if it was ever... fixed. |
| ||
It wasn't... :D So what to do? Blame the coders... ;) |
| ||
You can always wrap the call in a Try Catch block... :-) |
| ||
Nevermind... it was a filename capitalization error. thanks! Last edited 2011 |
| ||
This is very interesting. Where do I download? |
| ||
The download instructions are here: http://www.blitzbasic.com/Community/posts.php?topic=71734#801600 Or are you having trouble? |
| ||
I wasn't able to register in the forums so I wasn't able to download. |
| ||
Ok now I downloaded the zipsteeam library. I created one zip file with name "test.zip" and I put one image .bmp with name "test_image.bmp" [code] global test_image:TImage test_image = LoadImage("zip::test.zip//test_image.bmp", MASKEDIMAGE) DrawImage(test_image, 0, 0, 0) [/cod] I have this error: Unhandled Exception:Attempt to access field or method of Null object What does this means? |
| ||
did you add this line to your code?SuperStrict Import koriolis.zipstream global test_image:TImage test_image = LoadImage("zip::test.zip//test_image.bmp", MASKEDIMAGE) DrawImage test_image, 0, 0, 0 |
| ||
Wow , perfect the image loaded. :D I wasn't loaded the library If I my zip have password how to load the image with the zip password? I found it I put this code before load everything from zip SetZipStreamPassword("test.zip", "12345") I think , this solve all my pack file problems. Thank you very very much AGAIN :D Last edited 2012 |
| ||
Is it possible to get this to work together with LoadDir? |
| ||
Where can I get this now? Link is dead with that irritating robots.txt EDIT: Never mind found it http://retroremakes-framework.googlecode.com/svn/trunk/modules/koriolis.mod/ EDIT 2: ZipStream appears not to work with minib3d when using loadMesh etc |
| ||
MiniB3D with Koriolis on PC and Mac? I often did combinations of Koriolis Zipstream and MiniB3D and it works on PC. On the MAC I needed to copy the files to a temp dir first. DatenPfad$="ZIP::Incbin::tt1.zip//" Global ImagePfad$=DatenPfad ?MacOS Print "mac os " ImagePfad=AppleResourceDir() Local CopyListe:TStream, CopyDatei$ CopyListe=OpenFile(DatenPfad + "MacCopy.lst") While Eof(CopyListe)=0 CopyDatei=ReadLine(CopyListe) Print "copy now " + copydatei If FileType(ImagePfad+CopyDatei)=0 Print "yes" CopyFile DatenPfad +CopyDatei, ImagePfad + CopyDatei EndIf Wend CloseFile CopyListe ? |
| ||
this comes in a module download with timeline as well. Plus I think the area which hosts all blitz modules has it. Do a search in google I don't have a bookmark. |