Zipping increment file names using Zip Utils - c++

Hello I've been using "Zip Utils" from
http://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win32
to zip files and folders. the easy thing is if the file name is known i just need to do something like this
HZIP hz; DWORD writ;
hz = CreateZip(_T("filename\\image1.zip"),0);
The problem is I get errors when trying to zip files by incrementing file names within a loop
int i= 0;
for(i=0; i<record; i++)
{
ZipAdd(hz,_T("doc"+i+1+".kml"), _T("filename\\doc"+i+1+".kml"));
}

This is not the most efficient way to write the code but it illustrates the concept. Use to_string( ... ) to convert a number to a string for concatenation. It requires a long long argument, not an int.
long long i;
string filepath1, filepath2;
for(i=0; i<record; i++)
{
filepath1 = "doc" + to_string(i + 1) + ".klm";
filepath2 = "GenFiles\\doc" + to_string(i + 1) + ".klm";
ZipAdd(hz,filepath1,filepath2);
}

Related

Found Old D Code That Needs Update

While digging around the internet in search of a tool that would allow me to extract sound files from a Java container, I found a 4+ year old bit of D code. Unfortunately, I couldn't get it to compile, and discovered upon searching Google that std.stream had been deprecated. I have never worked with D before now, however, and I can't find any clear-cut ideas on how to bring this pre-stream-death code up to speed. Are there any current D programmers who can help me out?
EDIT: I have picked up the undead src files stream and related files, but I am now having an int property issue. According to the forum where I found this code, it worked at the time of posting 4 years ago so I can't imagine that the 'files.sort' is inherently problematic.
import std.stdio;
import std.file;
import std.conv;
import std.stream;
import std.bitmanip;
void main(string args[]){
Stream pkfile = new BufferedFile(args[1],FileMode.In);
int headersize;
int counter = 0;
int filecount;
int throwaway;
int offset;
pkfile.read(headersize);
pkfile.read(filecount);
writefln("Count is : " ~ to!string(filecount));
int[] files = new int[filecount];
for(int x = 0; x < filecount; x++)
{
pkfile.read(throwaway);
pkfile.read(offset);
files[x] = offset + (headersize + 4);
}
files = files.sort;
for(int x =0; x < filecount; x++)
{
pkfile.seekSet(cast(long)files[x]);
long len;
pkfile.read(len);
int newlen = cast(int)len;
ubyte[] ogg = new ubyte[newlen];
pkfile.read(ogg);
string outname = getcwd() ~"/"~ to!string(counter) ~ ".ogg";
Stream oggout = new BufferedFile(outname,FileMode.OutNew);
oggout.write(shiftL(ogg,newlen));
oggout.close();
writefln("Creating file " ~ to!string(counter) ~".ogg");
counter++;
}
}
ubyte[] shiftL(ubyte[] ogg,int ogglength){
ubyte[] temp = new ubyte[ogglength];
for(int x = 0;x < ogglength;x++){
temp[x] = cast(byte)(ogg[x]-1);
}
return temp;
}
The easiest way is just to grab a copy of std.stream.
But for rewriting, I'd read the full file into memory and then slice it as you read bits of it.

Refactoring: Move (F6) in CLion - why does it work like that?

I have in my main.cpp this function:
double median(double values[], int count) {
int i, j, n = count, t;
for (i = 1 ; i <= n - 1 ; i++)
{
for (j = 1 ; j <= n - i ; j++)
{
if (values[j] <= values[j + 1])
{
t = (int) values[j];
values[j] = values[j + 1];
values[j + 1] = t;
}
}
}
if ( n % 2 == 0)
return (values[n / 2] + values[n / 2 + 1]) / 2.0 ;
else
return values[n / 2 + 1];
}
and I want to move that function into another file. So, I click on this function and then click F6 and then I write some name of the file eg. MathFunctions and then I end up with:
MathFunctions.h:
#ifndef PROJECT_NAME_MATHFUNCTIONS_H
#define PROJECT_NAME_MATHFUNCTIONS_H
#endif //PROJECT_NAME_MATHFUNCTIONS_H
MathFunctions.cpp:
#include "MathFunctions.h"
double median(double values[], int count) {
int i, j, n = count, t;
for (i = 1 ; i <= n - 1 ; i++)
{
for (j = 1 ; j <= n - i ; j++)
{
if (values[j] <= values[j + 1])
{
t = (int) values[j];
values[j] = values[j + 1];
values[j + 1] = t;
}
}
}
if ( n % 2 == 0)
return (values[n / 2] + values[n / 2 + 1]) / 2.0 ;
else
return values[n / 2 + 1];
}
I'm a beginner in C++ and I don't understand why this is working like that. I'd rather expect it to put declarations of methods like:
double median(double values[], int count);
In *.h file and the interior of the method in *.cpp file and then include the *.h file in my main.cpp like that:
#include "MathFunctions.h"
Can someone explain me why this is working like that? What am I supposed to do with the files created by CLion? Should I include MathFunctions.cpp instead of header file in my main.cpp?
Unfortunately this is a CLion bug, tracked by https://youtrack.jetbrains.com/issue/CPP-9329, please create a Jetbrains account and vote for this issue.
I am not sure what you mean by "workaround". To make your code working, you need to
Create the function declaration for double median(double values[], int count); in the MathFunctions.h include file.
In your main.cpp, add #include "MathFunctions.h as you mention
In CMakeLists.txt (and this is not CLion specific, you need to know the basics of CMake), add file MathFunctions.cpp to the list of source files for your executable.
For example, assuming you have a CLion-created CMakeLists.txt, you should have something similar to
set(SOURCE_FILES main.cpp MathFunctions.cpp)
add_executable(foo ${SOURCE_FILES})
Some other random comments:
median() is not a "method", it is a "function", or more precisely a "free-standing function" (that is, a function that is not part of a class).
median() is not really C++, is C, since it uses a low-level C array. You may want to use a std::vector<double> instead.
C and C++ are low-level and, depending from which languages you are coming from, can be confusing :-) I suggest picking a good, recent book on modern C++. Modern C++ refers to at least C++11 and a style of programming where you almost never perform direct memory allocation/deallocation (that is, you don't use new and delete). Good luck in your journey!
Edit
Changed link to Jetbrains bug to the first one reporting the issue.

How to use variable string in a loop?

I have written a program in which I save an image during a loop, with this command
writeimagefile("f:\\chkng\\otp.bmp",0,0,scn,scn);
This command is from graphics.h, which writes the image file in the given location. How should I save the image every loop with a different name? i.e otp1.bmp, otp2.bmp, otp3.bmp.
for (int i = start; i != end; ++i )
{
char filename[100];
sprintf(filename, "f:\\chkng\\otp%d.bmp", i);
writeimagefile(filename,0,0,scn,scn);
}
For this, I'm assuming that your loop is index based (counts from 0 to a max). I'm also assuming that you've included string.
int max = 1; //example
for(int i=0;i<max;i++){
std::string filename = "f:\\chkng\\otp" + std::to_string(i) + ".bmp";
writeimagefile(filename.c_str(),0,0,scn,scn);
}
Explanation:
What I'm doing here is using a loop, building a string with a number in the filename as requested, and calling your function with the c_str version (what your function wants) of the filename we just built.
For loops work well for counting things, and in many languages the example you're showing can be done by concatenating the count into the filename string. Try something like the following:
for (int count = startingNumber; count <= endingNumber; count++)
{
writeimagefile("f:\\chkng\\otp" + count + ".bmp",0,0,scn,scn);
}

Where did these .tmp files come from?

Firstly, some details:
I am using a combination of C++ (Armadillo library) and R.
I am using Ubuntu as my operating system.
I am not using Rcpp
Suppose that I have some C++ code called cpp_code which:
Reads, as input from R, an integer,
Performs some calculations,
Saves, as output to R, a spreadsheet "out.csv". (I use .save( name, file_type = csv))
Some simplified R code would be:
for(i in 1:10000)
{
system(paste0("echo ", toString(i), " | ./cpp_code")) ## produces out.csv
output[i,,] <- read.csv("out.csv") ## reads out.csv
}
My Problem:
99% of the time, everything works fine. However, every now and then, I keep getting some unusual .tmp files like: "out.csv.tmp_a0ac9806ff7f0000703a". These .tmp files only appear for a second or so, then suddenly disappear.
Questions:
What is causing this?
Is there a way to stop this from happening?
Please go easy on me since computing is not my main discipline.
Thank you very much for your time.
Many programs write their output to a temporary file, then rename it to the destination file. This is often done to avoid leaving a half-written output file if the process is killed while writing. By using a temporary, the file can be atomically renamed to the output file name ensuring either:
the entire output file is properly written or
no change is made to the output file
Note there usually are still some race conditions that could result, for example, in the output file being deleted but the temporary file not renamed, but one of the two outcomes above is the general goal.
I believe you're using .save function in armadillo.
http://arma.sourceforge.net/docs.html#save_load_field
There are two functions you should see in
include/armadillo_bits/diskio_meat.hpp. In save_raw_ascii, it first stores data to the filename from diskio::gen_tmp_name, and if save_okay, rename by safe_rename. If safe_okay or safe_rename failed, you will see temporary file. The temporary file name is chosen as filename + .tmp_ + some hex value from file name.
//! Save a matrix as raw text (no header, human readable).
//! Matrices can be loaded in Matlab and Octave, as long as they don't have complex elements.
template<typename eT>
inline
bool
diskio::save_raw_ascii(const Mat<eT>& x, const std::string& final_name)
{
arma_extra_debug_sigprint();
const std::string tmp_name = diskio::gen_tmp_name(final_name);
std::fstream f(tmp_name.c_str(), std::fstream::out);
bool save_okay = f.is_open();
if(save_okay == true)
{
save_okay = diskio::save_raw_ascii(x, f);
f.flush();
f.close();
if(save_okay == true)
{
save_okay = diskio::safe_rename(tmp_name, final_name);
}
}
return save_okay;
}
//! Append a quasi-random string to the given filename.
//! The rand() function is deliberately not used,
//! as rand() has an internal state that changes
//! from call to call. Such states should not be
//! modified in scientific applications, where the
//! results should be reproducable and not affected
//! by saving data.
inline
std::string
diskio::gen_tmp_name(const std::string& x)
{
const std::string* ptr_x = &x;
const u8* ptr_ptr_x = reinterpret_cast<const u8*>(&ptr_x);
const char* extra = ".tmp_";
const uword extra_size = 5;
const uword tmp_size = 2*sizeof(u8*) + 2*2;
char tmp[tmp_size];
uword char_count = 0;
for(uword i=0; i<sizeof(u8*); ++i)
{
conv_to_hex(&tmp[char_count], ptr_ptr_x[i]);
char_count += 2;
}
const uword x_size = static_cast<uword>(x.size());
u8 sum = 0;
for(uword i=0; i<x_size; ++i)
{
sum += u8(x[i]);
}
conv_to_hex(&tmp[char_count], sum);
char_count += 2;
conv_to_hex(&tmp[char_count], u8(x_size));
std::string out;
out.resize(x_size + extra_size + tmp_size);
for(uword i=0; i<x_size; ++i)
{
out[i] = x[i];
}
for(uword i=0; i<extra_size; ++i)
{
out[x_size + i] = extra[i];
}
for(uword i=0; i<tmp_size; ++i)
{
out[x_size + extra_size + i] = tmp[i];
}
return out;
}
What “Dark Falcon” hypothesises is exactly true: when calling save, Armadillo creates a temporary file to which it saves the data, and then renames the file to the final name.
This can be seen in the source code (this is save_raw_ascii but the other save* functions work analogously):
const std::string tmp_name = diskio::gen_tmp_name(final_name);
std::fstream f(tmp_name.c_str(), std::fstream::out);
bool save_okay = f.is_open();
if(save_okay == true)
{
save_okay = diskio::save_raw_ascii(x, f);
f.flush();
f.close();
if(save_okay == true)
{
save_okay = diskio::safe_rename(tmp_name, final_name);
}
}
The comment on safe_rename says this:
Safely rename a file.
Before renaming, test if we can write to the final file.
This should prevent:
overwriting files that are write protected,
overwriting directories.
It’s worth noting that this will however not prevent a race condition.

C++: how to output data to multiple .dat files?

I have a research project I'm working on. I am a beginner in C++ and programming in general. I have already made a program that generates interacting particles that move on continuous space as time progresses. The only things my program outputs are the XY coordinates for each particle in each time-step.
I want to visualize my findings, to know if my particles are moving as they should. My professor said that I must use gnuplot. Since I could not find a way to output my data in one file so that gnuplot would recognize it, I thought of the following strategy:
a) For each time-step generate one file with XY coordinates of the form "output_#.dat".
b) Generate a .png file for each one of them in gnuplot.
c) Make a movie of the moving particles with all the .png files.
I am going to worry about b and c later, but up to now, I am able to output all my data in one file using this code:
void main()
{
int i = 0;
int t = 0; // time
int j = 0;
int ctr = 0;
double sumX = 0;
double sumY = 0;
srand(time(NULL)); // give system time as seed to random generator
Cell* particles[maxSize]; // create array of pointers of type Cell.
for(i=0; i<maxSize; i++)
{
particles[i] = new Cell(); // initialize in memory
particles[i]->InitPos(); // give initial positions
}
FILE *newFile = fopen("output_00.dat","w"); // print initial positions
for(i=0; i<maxSize; i++)
{
fprintf(newFile, "%f %3 ", particles[i]->getCurrX());
fprintf(newFile, "%f %3 \n", particles[i]->getCurrY());
}
fclose(newFile);
FILE *output = fopen("output_01.dat","w");
for(t = 0; t < tMax; t++)
{
fprintf(output, "%d ", t);
for(i=0; i<maxSize; i++) // for every cell
{
sumX = 0;
sumY = 0;
for(j=0; j<maxSize; j++) // for all surrounding cells
{
sumX += particles[i]->ForceX(particles[i], particles[j]);
sumY += particles[i]->ForceY(particles[i], particles[j]);
}
particles[i]->setVelX(particles[i]->getPrevVelX() + (sumX)*dt); // update speed
particles[i]->setVelY(particles[i]->getPrevVelY() + (sumY)*dt);
particles[i]->setCurrX(particles[i]->getPrevX() + (particles[i]->getVelX())*dt); // update position
particles[i]->setCurrY(particles[i]->getPrevY() + (particles[i]->getVelY())*dt);
fprintf(output, " ");
fprintf(output, "%f %3 ", particles[i]->getCurrX());
fprintf(output, "%f %3 \n", particles[i]->getCurrY());
}
}
fclose(output);
}
This indeed generates 2 files, output_00.dat and output01.dat with the first one containing the initial randomly generated positions and the second one containing all my results.
I can feel that in the nested for loop, where I'm updating the speed and position for the XY coordinates, I can have a FILE* that will store the coordinates for each time step and then close it, before incrementing time. In that way, I will not need multiple pointers to be open at the same time. At least that is my intuition.
I do not know how to generate incrementing filenames. I have stumbled upon ofstream, but I don't understand how it works...
I think what I would like my program to do at this point is:
1) Generate a new file name, using a base name and the current loop counter value.
2) Open that file.
3) Write the coordinates for that time-step.
4) Close the file.
5) Repeat.
Any help will be greatly appreciated. Thank you for your time!
Using ofstream instead of fopen would be a better use of the C++ standard library, whereas now you are using C standard library calls, but there is nothing wrong per se with what you are doing doing now.
It seems like your real core question is how to generate a filename from an integer so you can use it in a loop:
Here is one way:
// Include these somewhere
#include <string>
#include <sstream>
// Define this function
std::string make_output_filename(size_t index) {
std::ostringstream ss;
ss << "output_" << index << ".dat";
return ss.str();
}
// Use that function with fopen in this way:
for (size_t output_file_number=0; /* rest of your for loop stuff */) {
FILE *file = fopen(make_output_filename(output_file_number).c_str(), "w");
/* use the file */
fclose(file);
}
This uses a std::ostringstream" to build a filename using stream operations, and returns the built std::string. When you pass it to fopen, you have to give it a const char * rather than a std::string, so we use the .c_str() member which exists just for this purpose.