Opening a zip file in C++ with XZIP - c++

In my current project, I have to go to a certain user inputted directory, open that directory and read all the zip files in that directory which begin with W. I am trying to use the XZIP library for opening the ZIP files, but I am certainly doing something very wrong. I am confused whether to use UnzipItem or Openzip to open the zip file and parse through its contents. (The zip files each contain some .jpg files and I have to copy those files into another location, but that's the second part of the project)
I would really appreciate some help, Thanks :)
Here is my code-
#include "StdAfx.h"
#include "src\XZip.h"
#include "src\XUnzip.h"
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include "src\dirent.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <windows.h>
int main()
{
std::ifstream fin;
std::string dir, filepath;
int num;
DIR *dp;
struct dirent *dirp;
struct stat filestat;
std::string filename;
std::string userInput;
std::cout << " Input dir to get files from : ";
getline( std::cin, dir ); // gets everything the user
dp = opendir( dir.c_str() );
if (dp == NULL)
{
std::cout << "Error opening " << dir << std::endl;
}
char test[2];
while ((dirp = readdir( dp )) != NULL)
{ // printf(" inside the directory ");
filepath = dir+"/" + dirp->d_name;
filename =dirp->d_name;
test[0]=filename[0];
test[1]='\0';
if ( test[0]=='W')
{ HZIP* z;
DWORD File_name = std::strtoul(filename.c_str(), NULL, 16);
OpenZip(z,0,File_name);
}
}
return 0;
}

From the docs I'd say that you first need to call OpenZip to get a handle back and with that handle call UzipItem with an item id you got from FindZipItem.
All i have is the documentation:
flags - indicates usage, see below; for files, this will be ZIP_FILENAME
So i guess something like: auto handle = OpenZip("file.zip", 0, ZIP_FILENAME);

Related

Type 'string' could not be resolved

Im new to coding c++ and i am trying to call a function from another file to check if the string containing the text file is made up of alphabetic characters, but for some reason it is not working.
I am getting errors in my ap.cpp file saying
Invalid arguments '
Candidates are:
bool is_alpha(?)
'
and
‘is_alpha’ cannot be used as a function
and also errors in my header file saying
Type 'string' could not be resolved
MY CODE:
AP.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
using namespace std;
int main () {
string line;
string textFile;
ifstream myfile ("encrypted_text");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
textFile += line;
}
myfile.close();
}
else cout << "Unable to open file";
bool check = is_alpha(textFile);
if (check){
cout << "true";
} else cout << "false";
return 0;
}
checkFunctions.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include "functions.h"
using namespace std;
bool is_alpha (string str) {
for(int i=0; i < str.size(); i++)
{
if( !isalpha(str[i]) || !isspace(str[i]))
{
return true;
}
}
return false;
}
functions.h
#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_
#include <string>
bool is_alpha(string str);
#endif /* FUNCTIONS_H_ */
It'll be the best if you not use using namespace std; until you have a proper understanding about the language and its implications. If you were wondering what using namespace does is, it basically sets the content in the namespace and puts it to the global namespace (in which you don't need to specify where it comes from, in this its std and the way to call it is std::).
The error is because the compiler doesn't know where the string in bool is_alpha(string str); comes from. So to solve this, take my first advice to consideration and you can specify where it comes from like this: bool is_alpha(std::string str);.
Plus you don't need to add the libraries included in a header file again in the source file. This means that you can remove the #include <string> from AP.cpp and checkFunctions.cpp.
More about header files: https://stackoverflow.com/a/9224641/11228029

I want to print the contents of a text file in the filepath. How do I fix it?

I want to print the text files name and contents of a text file in the filepath.
i tried change filepath to c:\temp\ but its error
i tried filtered text file this point in if strchr point
i tried to output txt files content in while loop
How do I fix it?
#define _CRT_SECURE_NO_WARNINGS
#include <io.h>
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string filepath = "C:\\TEMP\\*.*"; <- i tried c:\\temp\\ but its error
struct _finddata_t fd;
intptr_t handle;
if ((handle = _findfirst(filepath.c_str(), &fd)) == -1L)
printf("file not fount");
do
{
if (strchr(fd.name,'txt')){ <- i tried filtered text file this point
printf("filename : %s \n", fd.name);
string in_line;
ifstream in(filepath + fd.name); <- i think error this point
while (getline(in, in_line)) {
cout << in_line << "\n"; <-i tried to output txt files content this point
}
in.close();
}
} while (_findnext(handle, &fd) == 0);
_findclose(handle);
return 0;
}

Saving a file in a different place for linux

I am trying to save a file somewhere else than the folder of the exe. I have pieced together this unelegant way:
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
using namespace std;
int main() {
//getting current path of the executable
char executable_path[256];
getcwd(executable_path, 255);
//unelegant back and forth conversion to add a different location
string file_loction_as_string;
file_loction_as_string = executable_path;
file_loction_as_string += "/output_files/hello_world.txt"; //folder has to exist
char *file_loction_as_char = const_cast<char*>(file_loction_as_string.c_str());
// creating, writing, closing file
ofstream output_file(file_loction_as_char);
output_file << "hello world!";
output_file.close();
}
Is there a more elegant way to do this? So that the char-string-char* is not necessary.
Also is it possible to create the output folder in the process apart from mkdir?
Thank you
You can get rid of 3 lines of code if you use the following.
int main()
{
//getting current path of the executable
char executable_path[256];
getcwd(executable_path, 255);
//unelegant back and forth conversion to add a different location
string file_loction_as_string = string(executable_path) + "/output_files/hello_world.txt";
// creating, writing, closing file
ofstream output_file(file_loction_as_string.c_str());
output_file << "hello world!";
output_file.close();
}

c++ combine path of file as a string with file name

I want to read some input files in my c++ code and I want to define the path of input files as a string and then combine it with file names. How can I do this? (Input_path + filename.dat)
#include <filesystem> //C++ 17
#include <iostream>
namespace fs = std::filesystem;
using namespace std;
void main()
{
string dir("c:\\temp");
string fileName("my_file.txt");
fs::path fullPath = dir;
fullPath /= fileName;
cout << fullPath.c_str() << endl;
}
You would use something like:
string path ("yourFilePath");
string filename ("filename");
You could then open the file like this:
ifstream inputFileStream;
inputFileStream.open(path + fileName);
Depending on your requirements, you will have to decide whether to use formatted or unformatted input when reading. I would read this for more information regarding that.
Cocatenation referenced from: C++ string concatenation
Reading referenced from: C++ read and write with files
Try any of these codes:
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string filepath = "D:/location/";
filepath+= "filename.dat";
std::ifstream fp;
fp.open(filepath.c_str(),std::ios_base::binary);
....PROCESS THE FILE HERE
fp.close();
return 0;
}
or
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string filepath = "D:/location/";
std::ifstream fp;
fp.open((filepath+"filename.dat").c_str(),std::ios_base::binary);
...............
fp.close();
return 0;
}
or use std::string::append
#include <iostream>
#include <string>
#include <fstream>
int main() {
std::string filepath = "D:/location/";
std::ifstream fp;
fp.open((filepath.append("filename.dat")).c_str(),std::ios_base::binary);
fp.close();
return 0;
}

output list of files from popen to ifstream.open

Basically I need to open and read a list of files I get from another command.
For each line of output of popen
open a file usen ifstream.open
it compiles and if I put the file name directly it works fine, but it doesn't do anything when using popen output. I've seen questions like this but none of this particular way of giving filenames.
here's the code:
#include <iostream>
#include <sqlite3.h>
#include <stdio.h>
#include <fstream>
using namespace std;
int main () {
ifstream singlefile;
FILE *filelist;
char filename[512];
string progline;
if(!(filelist = popen("find `pwd` -name \"*.js\"", "r"))){
return 1;
}
while( fgets(filename, sizeof(filename), filelist)!=NULL)
{
cout << filename;
singlefile.open(filename, ifstream::in);
while ( singlefile.good() )
{
getline (singlefile,progline);
cout << progline << endl;
}
singlefile.close();
}
pclose(filelist);
return 0;
}
next step would be not open each file inside the loop but to store the file list and then open each file.
Thanks
fgets keeps the trailing newline, resulting in a filename of a non-existing file. Also the stream state is only updated after reading. If I replace the while body with the following code, it works for me:
cout << filename;
size_t len = strlen(filename);
// chop off trailing newline
if (len > 1 && filename[len - 1] == '\n') filename[len - 1] = 0;
singlefile.open(filename, ifstream::in);
while ( getline(singlefile, progline) )
{
cout << progline << endl;
}
singlefile.close();
If you actually want to iterate through a list of files, I'd use Boost.Filesystem, which has a nice C++ interface, works for all filenames (even for those with newlines), and is platform-independent.
If this actually is only an example and your actual command is not find, there is still some room for simplification. Here is a suggestion that uses Boost.Iostreams to get rid of most of the C function calls (it would be great to have a device source reading from a process's standard output, but Boost.Iostreams lacks that):
#include <cstdio>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <stdio.h>
#include <boost/noncopyable.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
using namespace std;
namespace io = boost::iostreams;
class Popen: private boost::noncopyable {
public:
explicit Popen(const char* command):
m_stream(popen(command, "r")) {
if (!m_stream) throw runtime_error("popen failed");
}
~Popen() {
pclose(m_stream);
}
FILE* stream() const {
return m_stream;
}
private:
FILE* m_stream;
};
int main() {
Popen pipe_wrapper("find `pwd` -name \"*.cpp\"");
io::file_descriptor_source pipe_device(fileno(pipe_wrapper.stream()), io::never_close_handle);
io::stream<io::file_descriptor_source> pipe_stream(pipe_device, 0x1000, 0x1000);
string filename;
while (getline(pipe_stream, filename)) {
cout << filename << endl;
ifstream file_stream(filename.c_str(), ifstream::in);
string progline;
while (getline(file_stream, progline)) {
cout << progline << endl;
}
}
}