I'm tring create zip file with libzip library.
list<string> ListOfFiles;
ListOfFiles.push_back("file1");
ListOfFiles.push_back("file2");
ListOfFiles.push_back("file3");
...
createZip(const char* destination)
{
int err;
zip *archive = zip_open(destination, ZIP_CREATE, &err);
cout << "1. " << zip_strerror(archive) << endl;
for (list<string>::iterator iter = ListOfFiles.begin(), end = ListOfFiles.end(); iter != end; iter++)
{
zip_source *source = zip_source_file(archive,iter->c_str(),0,0);
cout << "2. " << zip_strerror(archive) << endl;
index = zip_file_add(archive, iter->c_str(), source, ZIP_FL_OVERWRITE);
cout << "3. " << zip_strerror(archive) << endl;
}
zip_close(archive);
cout << "4. " << zip_strerror(archive) << endl;
}
output:
No error
No error
Invalid argument ...
Read error: No such file or directory
When I tried create zip, error value return "Invalid argument" after i tried added file to zip.
For further help here is my code that worked for me.
int main() {
int err = 0;
ifstream fs, fs1;
fs.open("my_test.txt", std::ios::binary);
fs1.open("f 2.pdf", std::ios::binary);
std::string content((std::istreambuf_iterator<char>(fs)), (std::istreambuf_iterator<char>()));
std::string content1((std::istreambuf_iterator<char>(fs1)), (std::istreambuf_iterator<char>()));
zip* z = zip_open("foo.zip", ZIP_CREATE, &err);
zip_source_t* zs;
zs = zip_source_buffer(z, content.c_str(), content.length(), 0);
zip_file_add(z, "test.txt", zs, ZIP_FL_OVERWRITE | ZIP_FL_ENC_UTF_8);
zs = zip_source_buffer(z, content1.c_str(), content1.length(), 0);
zip_file_add(z, "test.pdf", zs, ZIP_FL_OVERWRITE | ZIP_FL_ENC_UTF_8);
zip_close(z);}
i opened 2 files (one txt and one pdf) in binary mode and read the entire files. I have store its data to two string contents. Next i have created the zip file (foo.zip), Next step is to create the source buffer. first argument is the zip file second is the content the third is the length of the content to be written. finally we add the buffer inside the zip. BE CAREFUL the zip_file_add creates new file with the name provided (my_test.txt-> text.txt and f 2.pdf -> test.pdf)
Related
my assignment asks me to open a file, but if it doesn't open you are given 3 tries, but when I input the correct file on my second and third try it still give me the error I wrote 'ERROR: File " << input_filename << " could not be opened for input"' and goes to my else statement
char input_filename[90];
ifstream input;
cout << "Type the name of the input file which will hold the simulation results : " << endl;
cin>> input_filename;
input.open(input_filename);
if (input.fail())//if the file doesn't open it will go to the do while loop error message
{
int i = 0;
int h = 0;
do
{
cout << "ERROR: File " << input_filename << " could not be opened for input" << endl;
cin >> input_filename;// allows user to reinput filename
input.open(input_filename);//opens file
if ( !input.fail())
{
cout << "if statement" << endl;
h++;// if h doesn't equal 1 it goes out of the loop
}
else
{
cout << "else statement" << endl;
i++;//post-decrement allows for 2 more tries to input file
}
if (i >= 2)
{
cout << "ERROR: You exceeded maximum number of tries allowed" << endl;
cout << "while entering the input file name" << endl;
return 1;// return 1 represents the error of the input not opening after the 3rd time of inputing
}
} while (i < 2 && h != 0);// do while because it need to be a post condition for two varibles
}
If you reach line 106, it implies your file input succeeded. At that line you should NOT increment h. In fact you should leave h at zero if you want to break out of the loop (Assuming the file input worked).
I have a code that I found on the internet that uses the function GetRawInputDeviceInfo, but it doesn't get the name of the device right. sometimes it doesn't get a name at all. I've searched for an answer and found out that people had this problem on windows XP and windows 7 to. I am using windows 10 so that doesn't really help me.
C++ - WinAPI get list of all connected USB devices (do i need to post the code itself? im new to stack overflow)
At the end of the day what I am trying to do is get the names of all the devices connected to my PC and print them out, but this function doesnt return the name of the mouse either, so if anyone has a suggestion on how to fix it or a better method to get the names Id'e love to hear you'r ideas. thanks in advance, -shon :)
EDIT2! the full code:
#include <windows.h>
#include <iostream>
#include <vector>
#include <string>
#include <set>
// Namespace
using namespace std;
// Main
int main()
{
// Program
cout << "USB Device Lister." << endl;
// Get Number Of Devices
UINT nDevices = 0;
GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Any?
if (nDevices < 1)
{
// Exit
cout << "ERR: 0 Devices?";
cin.get();
return 0;
}
// Allocate Memory For Device List
PRAWINPUTDEVICELIST pRawInputDeviceList;
pRawInputDeviceList = new RAWINPUTDEVICELIST[sizeof(RAWINPUTDEVICELIST) * nDevices];
// Got Memory?
if (pRawInputDeviceList == NULL)
{
// Error
cout << "ERR: Could not allocate memory for Device List.";
cin.get();
return 0;
}
// Fill Device List Buffer
int nResult;
nResult = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
// Got Device List?
if (nResult < 0)
{
// Clean Up
delete[] pRawInputDeviceList;
// Error
cout << "ERR: Could not get device list.";
cin.get();
return 0;
}
std::set<std::string> DeviceList;
// Loop Through Device List
for (UINT i = 0; i < nDevices; i++)
{
// Get Character Count For Device Name
UINT nBufferSize = 0;
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
NULL, // NO Buff, Want Count!
&nBufferSize); // Char Count Here!
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name character count.. Moving to next device." << endl << endl;
// Next
continue;
}
// Allocate Memory For Device Name
WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];
// Got Memory
if (wcDeviceName == NULL)
{
// Error
cout << "ERR: Unable to allocate memory for Device Name.. Moving to next device." << endl << endl;
// Next
continue;
}
// Get Name
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice, // Device
RIDI_DEVICENAME, // Get Device Name
wcDeviceName, // Get Name!
&nBufferSize); // Char Count
// Got Device Name?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to get Device Name.. Moving to next device." << endl << endl;
// Clean Up
delete[] wcDeviceName;
// Next
continue;
}
// Set Device Info & Buffer Size
RID_DEVICE_INFO rdiDeviceInfo;
rdiDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO);
nBufferSize = rdiDeviceInfo.cbSize;
// Get Device Info
nResult = GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,
RIDI_DEVICEINFO,
&rdiDeviceInfo,
&nBufferSize);
// Got All Buffer?
if (nResult < 0)
{
// Error
cout << "ERR: Unable to read Device Info.. Moving to next device." << endl << endl;
// Next
continue;
}
// Mouse
if (rdiDeviceInfo.dwType == RIM_TYPEMOUSE)
{
// Current Device
int id = rdiDeviceInfo.mouse.dwId; //device id
string s = "ID: " + std::to_string(id) + ", Type : MOUSE"; //device type is mouse
DeviceList.insert(s);
}
// Keyboard
else if (rdiDeviceInfo.dwType == RIM_TYPEKEYBOARD)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (KEYBOARD)" << endl;
wcout << L"Name " << wcDeviceName << endl; //*Problem is here!* //
cout << "Keyboard mode: " << rdiDeviceInfo.keyboard.dwKeyboardMode << endl;
cout << "Number of function keys: " << rdiDeviceInfo.keyboard.dwNumberOfFunctionKeys << endl;
cout << "Number of indicators: " << rdiDeviceInfo.keyboard.dwNumberOfIndicators << endl;
cout << "Number of keys total: " << rdiDeviceInfo.keyboard.dwNumberOfKeysTotal << endl;
cout << "Type of the keyboard: " << rdiDeviceInfo.keyboard.dwType << endl;
cout << "Subtype of the keyboard: " << rdiDeviceInfo.keyboard.dwSubType << endl;
}
// Some HID
else // (rdi.dwType == RIM_TYPEHID)
{
// Current Device
cout << endl << "Displaying device " << i + 1 << " information. (HID)" << endl;
wcout << L"Device Name: " << wcDeviceName << endl;
cout << "Vendor Id:" << rdiDeviceInfo.hid.dwVendorId << endl;
cout << "Product Id:" << rdiDeviceInfo.hid.dwProductId << endl;
cout << "Version No:" << rdiDeviceInfo.hid.dwVersionNumber << endl;
cout << "Usage for the device: " << rdiDeviceInfo.hid.usUsage << endl;
cout << "Usage Page for the device: " << rdiDeviceInfo.hid.usUsagePage << endl;
}
// Delete Name Memory!
delete[] wcDeviceName;
}
// Clean Up - Free Memory
delete[] pRawInputDeviceList;
for (std::set<string>::iterator i = DeviceList.begin(); i != DeviceList.end(); ++i)
std::cout << *i << '\n';
// Exit
cout << endl << "Finnished.";
cin.get();
return 0;
}
In Windows there are two flavors of API calls: Unicode and ANSI. The former takes and returns UTF-16 encoded Unicode strings; the latter takes and returns 8-bit encoded strings (the exact encoding depends on the OS localization).
You choose which flavor you want to use by #defining (or not #defining) the macro UNICODE. Depending on that the function changes name, with an W or A suffix.
#ifdef UNICODE
#define GetRawInputDeviceInfo GetRawInputDeviceInfoW
#else
#define GetRawInputDeviceInfo GetRawInputDeviceInfoA
#endif
All the structures that may contain text data are also duplicated with the W or A suffixes.
Now your problem: you are not defining UNICODE so you are actually calling GetRawInputDeviceInfoA(), the ANSI flavor, that expects a char*, but you are passing a WCHAR*, that is a UNICODE string!
The solution is easy:
char* wcDeviceName = new char[nBufferSize + 1];
It is unfortunate that this function GetRawInputDeviceInfo() has its arguments overloaded, so it is declared as taking a void*, so the compiler cannot catch the error. If you were calling a simpler function, say SetWindowText() then you would have got a compiler error because of incompatible pointer type.
If you really want the full UNICODE name of the device, you may prefer keep the WCHAR string and then call the UNICODE function specifically:
WCHAR* wcDeviceName = new WCHAR[nBufferSize + 1];
...
GetRawInputDeviceInfoW(..., RIDI_DEVICENAME, wcDeviceName, ...);
I am working on a portion of my code that is suppose to output the error message correctly.
Please see below screenshot, I am using on bash
./myProgram < input3a.in | diff -a -y output3a.out -
Left hand side is what I want to get to.
For some reason an extra "|" is printed before the char array 'line' is printed. I suspected that maybe the char array 'line' is not null terminated. but it is initialize by cin.getline(); which should null terminate the char array.
Here i try to print the 'line' array in my main procedure, and it left the | sign on the line before it.
my question is. why does std::cout display this behaviour?
Thanks
EDIT,
Below is my code in question. Thanks for taking a look again.
#include "char_stack.h"
#include <iostream>
void printErrorLine(int errorSpot, int c_count, char line[]){
//Print the first line of error message char by char, at the
//same time replace char with \t or space
for(int x = 0; x <= errorSpot; x++){
std::cout << line[x];
if(line[x] != '\t'){
line[x] = ' ';
}
}
std::cout << std::endl;
//Print out the second line, if the first line does not have a
//errorSpot, then dont print it
if(errorSpot != c_count){
std::cout << line << std::endl;
}
}
char findCounterPart(char bracket){
//pass.
}
int main(int argc, char * argv[]){
char line[250]; // 250 because spec sheet detailed max 250 char per line.
char c;
int l_count = 0; // number of lines already read
int c_count; // character count in a line
char_stack S;
bool isError;
while(!std::cin.peek() == std::cin.eof()){
std::cin.getline(line, 250);
c_count = std::cin.gcount();
l_count +=1;
//std::cout<< c_count << std::endl << std::endl;
//loop through the line
for(int x = 0; x < c_count; x++){
c = line[x];
//std::cout << c << " stack size is " << S.size() << std::endl;
if (c == '(' ||
c == '{' ||
c == '['){
S.push(c);
}
else if(c == ')' ||
c == '}' ||
c == ']'){
if(S.empty()){
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
isError = true;
}
else{
char l = S.pop();
if(l != findCounterPart(c)){
std::cout << "Error on line " << l_count << ": Read " << c <<
", expected " << findCounterPart(l) << std::endl;
isError = true;
}
}
}
if (isError){
printErrorLine(x, c_count ,line);
return 0;
}
}
}
if (!S.empty()){
c = S.pop();
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
printErrorLine(c_count, c_count , line);
}
else{
std::cout <<"No Errors Found" << std::endl;
}
return 0;
}
Learning to be a software engineer is about breaking problems down into manageable chunks, and here we have a couple of doosies. Lets rephrase your question slightly:
I am getting unexpected characters displayed when diff the output of my program against a file containing output of a previous run. Currently I think this is because of some weird behavior of std::cout.
Well, that might be a reasonable assumption, we can't see your code so we can't know if you're doing anything peculiar.
But it would have to be: std::cout is used, well, all over the place. It just doesn't have this behavior unless your code is deliberately writing a | somewhere.
There are a number of steps we could take to resolve this:
Run the program a 3rd time in the debugger and step through until you have some ideas where the '|' is appearing,
Run the program a 3rd time to the console and observe the output,
View the output using a command like cat, less or more, instead of diff
3 is perhaps the most sensible place to start, since the file is already right there and after that #2 will give us a mk1eyeball check.
What we find is: the | does not appear in the file or the output. It's not coming from your program.
Lets create a couple of .txt files and diff them:
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nSecond line' >test1.txt
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nFile two line 2' >test2.txt
osmith#WOTSIT MINGW64 ~
$ diff -a -y test1.txt test2.txt
First line First line
Second line | File two line 2
When using the -y switch, between the two columns of output, diff has a line of special characters to indicate lines that changed, were inserted or deleted.
So i have a program which reads the input out of a specific .txt file. The code is:
void Image::get_image_dimensions(char *fname)
{
// determine the number of entries in image
ifstream fin(fname);
fin >> num_rows ;
fin >> num_columns ;
cout << "...reading from file " << fname << endl;
cout << "File has " << num_columns << " rows and "<< num_columns << " columns" << endl;
fin.close();
}
the method is called inside the main.
After I compile the program with VS2010 and run the code everything works properly. But after if I go to the Debug folder of my program and run my program from there it doesn't read the input anymore, and crashes...
What might be the problem?
The current directory is different in the two cases. The best solution is to provide the full path to the file, not just the file name.
for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
{
if (iter->path().extension() == ".png"){
fs::path currentPath = iter->path();
const char *filename = const_cast<char*>(currentPath.string().c_str());
std::cout << iter->path().leaf() << std::endl;
processFile(filename);
std::cout <<"Hi" << std::endl;
}
}
This is my code and here processFile functions accepts the filename in char* format. Above code returns a junk value of filename. Don't know what is the best way to get the filename.
It works fine for me here (Boost.1.52, Mac OS X, clang).
Though I have to agree with Miguel, you're doing way to much work here.
for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
if (iter->path().extension() == ".png") {
fs::path currentPath = iter->path();
std::cout << currentPath.leaf() << std::endl;
processFile(currentPath.c_str ());
}
and depending on your taste in code, you could get rid of currentPath altogether ( replace it with iter->path() )