Jump to content
Gandi

Extract file from .pak

Recommended Posts

I want to store game specific data in a .pak file which I load with the C++ ifstream.

However, if I do something like:

 

ifstream file;
file.open(AbstractPath("abstract::myfile.txt"));

 

it obviously doesn't work, because only the engine's LoadXY() - functions can read from zip-files.

However, I'm pretty sure that the engine can already extract files from .pak's because of the cache:: - protocol, so something like

 

ifstream file;

//This returns the path of the cached file
str path = CacheFile("abstract::myfile.txt");

file.open(path);

 

Would be great^^

Share this post


Link to post

You can use ZLib (includes MiniZip): http://www.winimage.com/zLibDll/minizip.html

And then you can read a text file into a C++ string:

/*
  unzips testfile.txt from C:\temp\test.zip
  and puts it in a string
*/
#include <cstdio>
#include <string>
#include <iostream>
#include "unzip.h" // MiniZip library

#define WRITEBUFFERSIZE (5242880) // 5Mb buffer

using namespace std;

string readZipFile(string zipFile, string fileInZip) {
   int err = UNZ_OK;                 // error status
   uInt size_buf = WRITEBUFFERSIZE;  // byte size of buffer to store raw csv data
   void* buf;                        // the buffer  
   string sout;                      // output strings
   char filename_inzip[256];         // for unzGetCurrentFileInfo
   unz_file_info file_info;          // for unzGetCurrentFileInfo   

   unzFile uf = unzOpen(zipFile.c_str()); // open zipfile stream
   if (uf==NULL) {
       cerr << "Cannot open " << zipFile << endl;
       return sout;
   } // file is open

   if ( unzLocateFile(uf,fileInZip.c_str(),1) ) { // try to locate file inside zip
       // second argument of unzLocateFile: 1 = case sensitive, 0 = case-insensitive
       cerr << "File " << fileInZip << " not found in " << zipFile << endl;
       return sout;
   } // file inside zip found

   if (unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0)) {
       cerr << "Error " << err << " with zipfile " << zipFile << " in unzGetCurrentFileInfo." << endl;
       return sout;
   } // obtained the necessary details about file inside zip

   buf = (void*)malloc(size_buf); // setup buffer
   if (buf==NULL) {
       cerr << "Error allocating memory for read buffer" << endl;
       return sout;
   } // buffer ready

   err = unzOpenCurrentFilePassword(uf,NULL); // Open the file inside the zip (password = NULL)
   if (err!=UNZ_OK) {
       cerr << "Error " << err << " with zipfile " << zipFile << " in unzOpenCurrentFilePassword." << endl;
       return sout;
   } // file inside the zip is open

   // Copy contents of the file inside the zip to the buffer
   cout << "Extracting: " << filename_inzip << " from " << zipFile << endl;
   do {
       err = unzReadCurrentFile(uf,buf,size_buf);
       if (err<0) {
           cerr << "Error " << err << " with zipfile " << zipFile << " in unzReadCurrentFile" << endl;
           sout = ""; // empty output string
           break;
       }
       // copy the buffer to a string
       if (err>0) for (int i = 0; i < (int) err; i++) sout.push_back( *(((char*)buf)+i) );
   } while (err>0);

   err = unzCloseCurrentFile (uf);  // close the zipfile
   if (err!=UNZ_OK) {
           cerr << "Error " << err << " with zipfile " << zipFile << " in unzCloseCurrentFile" << endl;
           sout = ""; // empty output string
       }

   free(buf); // free up buffer memory
   return sout;
}

int main(int argc, char *argv[]) {
   string string_buffer = readZipFile("C:/temp/test.zip", "testfile.txt");
   cout << string_buffer << endl;
   return 0;
}

Share this post


Link to post

Yeah I know how to unzip files, but I thought this was an easy-to-implement and though useful function, so I made a request.

Share this post


Link to post

+10

 

i have a (mapname).set file that holds the fog values for that particular map, it would be neat to hide it in the .pak(password protected), so it's harder to cheat by turning them off in the .set file.

Share this post


Link to post

+1 here

 

Since the engine is capable of loading a file directly from the .pak as it does with LoadModel, LoadMesh etc. could be very useful to give us a command LoadFile("abstract::mydata.dat") which returns the content of file as string (and we can parse it splitting, deserializing etc).

 

I would need it for the Gamelib porting too since atm I'm writing a file system managament by myself for the AbstractPath problem

Share this post


Link to post

I agree with ZR on the LoadFile type command, but instead of a string, if we could simply get a pointer to the file's memory, and then from there we can get it as binary, XML, text, or whatever, in any encoding.

Share this post


Link to post

I agree with ZR on the LoadFile type command, but instead of a string, if we could simply get a pointer to the file's memory, and then from there we can get it as binary, XML, text, or whatever, in any encoding.

agree

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...