Can't open compressed file - c++

I'm trying to compress a text file with QT:
QFile inFile("d:\\build\\Directories\\Debug\\files\\developer.txt");
bool open_file_result = inFile.open(QIODevice::ReadOnly);
QByteArray ba = inFile.readAll();
QFile file("d:\\build\\Directories\\Debug\\files\\developer.gz");
bool open_zip_result = file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << qCompress(ba);
file.close();
open_file_result and open_zip_result are both true. I can also see the zip file (it also has a size, such as 50KB) but I can't open it. I'm getting the following error:
The archive is either in unknown format or damaged.
What am I doing wrong? If you have a better/another way to compress a text file, please tell me!

There is a difference between the Zip compression algorithm and the Zip container. You're confusing the two.
You need to do some research into the Zip container format that will help you locate and extract a zipped file within a Zip container. Once you've gotten that file, you can apply qUncompress to that file only.
Try looking at the QuaZip, which is a library that has been written for this purpose.

Related

How do I load QBytesArray containing a zip file to QuaZip?

I'm using Qt Creator in a new project, so I don't know many things about this... :(
I want to download a zip file, containing a json file, read this file and use that information. I can download the zip, save it in my disk and open it again to read json and use it. But I want to open my zip just in memory without really saving it...
I have the zip info in a QByteArray and I need to send this "file" to QuaZip constructor/object.
How do I do it?
You can use QBuffer. It provides a QIODevice interface for a QByteArray.
Example:
QByteArray byteArray("abc");
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
buffer.seek(3);
buffer.write("def", 3);
buffer.close();
Then you can use QuaZip::QuaZip(QIODevice *ioDevice) constructor to create QuaZip object.

How to make a QByteArray from a Database file

Using QByteArray QIODevice::readAll() from QT5, I was able to make a bytes array from a txt file or an image, used decode after and recreated the file correctly. But, when I tried with a .db file (SQLITE) it didn't work.
I noticed that when you open a .db with a text editor, you will see "SQLite format 3" followed by encoded characters. After making a QByteArray from a .db file, followed by decode() to recreate the file, when I opened it with a text editor, the file only contains the text "SQLite format 3".
Does QByteArray only work with txt file or Image file?
If it does, how can I make a Array of bytes from a .db (SQLITE) file.
Thanks
Update1 (The code belows works):
QFile file("C:/database.db");
if(!file.open(QIODevice::ReadOnly))
qDebug()<<"You are stupid!";
QByteArray byteArray = file.readAll();
QFile file2("C:/database2.db");
file2.open(QIODevice::WriteOnly);
file2.write(byteArray);
file2.close();
file.close();
Update2:
About the decode I mentioned in my initial question, I was using the following:
QString QFile::decodeName(const QByteArray & localFileName)
which make no sense when you read carefully the documentation and was just wrong. :)
You should not open that file with QIODevice::Text flag.
Check this http://doc.qt.io/qt-5/qiodevice.html#OpenModeFlag-enum

Creating compressed file in C++ without knowing the initial file size

I've been using Java's standard library for writing Zip Archive files and, in that case, I do not have to know the files that are going to be stored into a zip file beforehand: I would simply create a new ZipEntry and then write into the ZipFile stream.
On the other hand, LibArchive and ZLib for C++ have to set the to-be-archived file information beforehand: in my case the data that I want to compress comes from an extern stream, and hence I cannot query the size of the stream itself. Is there a library/way to use those libraries such that the initial file information is not required?
EDIT Moreover, the following C++ code with LibArchive produces a valid ZIP file containing a file with no data.
a = archive_write_new();
archive_write_add_filter_gzip(a);
archive_write_set_format_pax_restricted(a);
archive_write_open_filename(a, path.c_str());
entry = archive_entry_new(); // Note 2
archive_entry_set_pathname(entry, entryName.c_str());
archive_entry_set_perm(entry, 0666);
archive_write_header(a, entry);
size_t s = archive_write_data(a, buff, len);
archive_entry_free(entry);
archive_write_close(a);
archive_write_free(a);
Check the sample on the official Zlib site. In sample bytes from source file compressed to the new file until EOF on source. File size of source file is not used.
The only thing you should change in sample to use your custom stream is this line:
strm.avail_in = fread(in, 1, CHUNK, source);
Use your function to get bytes from stream to fill in buffer.
To handle ZIP archive in Zlib use contrib/minizip. Here is a discussion on how to use it.

Read file in zip without unzip(c++)

I can read file in c++. This is my code:
std::string ReadFile(std::string file)
{
char buff[20480];
std::ifstream fread(file, std::ios::binary | std::ios::app);
fread.read(buff,sizeof(buff));
std::string str = buff;
fread.close();
return str;
}
The variable "file" is the FilePath. And I get a folder .zip, I want to read the file in folder. What should I do? I try to use libzip, but it can't solve my problem, maybe I didn't use it by wrong way.
No. To unzip a file, you must unzip a file.
You don't need to invoke the unzip utility to do it: there are libraries that can expose decompression through a streams API, resulting in code that looks rather similar to what you've written above. But you need to install and learn how to use those libraries.
Unless you have access to the API that allows to unpack your file I don't see how directly in the code.
If you are lazy you could write a small script in whatever language you prefer that does the unpacking and then calls your program on the unpacked file
Assuming, you have unzip available. Did you try something like:
FILE * file = popen("unzip -p filename", "r");
Similarly, popen("gzip -f filename", "r") should work for gzip.
In order to parse the output, I'd refer to this post (with Windows hints). I don't know about a more C++-style way of doing this.

How to archive and compress data with "PhysicsFS"

I'm looking in "PhysicsFS" documentation and search for way to archive and compress data but can't find.Is it possible and if it is how i can do that
PhysicsFS zip support
PhysicsFS has support for reading files from a zip file mounted at an arbitrary point in the "virtual filesystem" that it provide. This effectively provide decompression from a ZIP archive.
However, PhysicsFS has no support to add or modify the content of a ZIP archive. It only permit to write uncompressed files in what is called "the write directory" in its documentation.
So, to summarize: PhysicsFS only support reading from ZIP archives, not writing to it.
For the compression you are on your own: just zip all the written files using an external compressor if you need so.
PhysicsFS usage
There is a small tutorial for PhysicsFS here.
It is very simple to use:
// initialize the lib
PHYSFS_init(NULL);
// "mount" a zip file in the root directory
PHYSFS_AddToSearchPath("myzip.zip", 1);
// set a directory for writing
PHYSFS_setWriteDir(const char *newDir);
// open a file for reading
PHYSFS_file* myfile = PHYSFS_openRead("myfile.txt");
// open a file for writing
PHYSFS_file* myfile = PHYSFS_openWrite("output_file.bin");
// get a file size
PHYSFS_sint64 file_size = PHYSFS_fileLength(myfile);
// read data from a file (decompress only if path is inside a zip mount point)
char* myBuf = new char[file_size];
int length_readed = PHYSFS_read(myfile, myBuf, 1, file_size);
// write data to a file (uncompressed)
char* myBuf = new char[new_file_size];
//...fill myBuf...
int length_writed = PHYSFS_write(myfile, myBuf, 1, new_file_size);
// close a file
PHYSFS_close(myfile);
// deinitialize the lib
PHYSFS_deinit();
Is it possible that you meant "PhysFS".
That is a library to read files from a zipfile. Basically like the Quake engine does.