What's Here?
- Members: 340,144
- Replies: 920,498
- Topics: 154,942
- Snippets: 4,855
- Tutorials: 1,257
- Total Online: 3,820
- Members: 126
- Guests: 3,694
|
Welcome to Dream.In.Code |
|
|
Become an Expert!
Join 340,144 Programmers for FREE! Get instant access to thousands  of experts, tutorials, code snippets, and more! There are 3,820 people online right now. Registration is fast and FREE... Join Now!
Chat LIVE With a Expert
|
My File Splitter function problem
My File Splitter function problem
File Splitter function only works with text formats, why?
Rate Topic:
   
Posted 21 May 2009 - 11:15 AM
This is the function which splits:
void kfs2(string in_name, long int max) {
stringstream sfename;
fstream in(in_name.c_str(), ios::binary|ios::in|ios::ate);
if(in.is_open()) {
long int fsize = in.tellg();
in.seekg(0, ios::beg);
long int r = fsize;
int i = 0;
char * buffer = new char[max+1];
fstream out;
int len = in_name.length();
while(max <= r) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
in.read(buffer, max);
out.open(sfename.str().c_str(), ios::out|ios::binary);
out.write(reinterpret_cast<const char *>(buffer), max);
out.close();
sfename.str("");
r -= max;
}
if(r>0) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
in.read(buffer, r);
out.open(sfename.str().c_str(), ios::out|ios::binary);
out.write(reinterpret_cast<const char *>(buffer), r);
out.close();
sfename.str("");
}
in.close();
out.close();
delete[] buffer;
}
}
Thanks.
Posted 21 May 2009 - 11:29 AM
To be honest with you, i can't believe it works with the text file....here is a simpler way. It's written in browser but it will atleast give you an idea
#include <fstream>
using namespace std;
bool split(char * file, char * output1, char *output2)
{
ifstream fin;
ofstream fout;
ofstream fout2;
int inputsize;
int half;
fin.open(file, ios::binary);
if (!fin)
{
return false;
}
fout.open(output1, ios::binary);
if (!fout)
{
return false;
}
fout2.open(output2, ios::binary);
if (!fout2)
{
return false;
}
fin.seekg(0, ios::end); //go to the end of the input
inputsize = fin.tellg(); //get current location in bytes
half = inputsize / 2;
char Buffer[inputsize]; //Create a buffer for the file to load into
fin.seekg(0, ios::beg); //go to beginning of file
fin.read(Buffer, inputsize); //This will load entire file into a buffer
fin.close(); //your done with that file!
for (int i = 0; i <= half; i++)
{
fout << Buffer[i];
}
fout.close(); //That would be the first half of the file
for (int i = half; i <= inputsize; i++)
{
fout2 << Buffer[i];
}
fout2.close(); // that would be the 2nd half of the file.
return true; //your done
}
That should give you atlease a basic idea.
Posted 21 May 2009 - 11:54 AM
Oops, sorry it seems that i must visit a doctor!  my code worked fine and runs smoothly...
Posted 21 May 2009 - 12:17 PM
Anarion, on 21 May, 2009 - 02:54 PM, said:
Oops, sorry it seems that i must visit a doctor!  my code worked fine and runs smoothly...
Thanks for posting that. I've been studying it for a while & couldn't find anything wrong.
Posted 21 May 2009 - 07:25 PM
What happens when when you run the code.
I don't have a reference with this, but I think when using fstream you have to open with ios::in and ios::out enabled. I seem to remember there is some trouble getting the file open otherwise... I just can't find a reference on it.
Posted 22 May 2009 - 11:22 PM
Sorry i disturbed you  but at least it works cool.
I used "ifstream" and "ofstream", they don't need the part "ios::in" or etc.
now i have to write the merge function to make t perfect, any ideas ? my idea is to generate an exe file that has the part-names inside it and when user executes it, the original file is made.
Posted 22 May 2009 - 11:39 PM
Anarion, on 22 May, 2009 - 11:22 PM, said:
my idea is to generate an exe file that has the part-names inside it and when user executes it, the original file is made.
I'm really not at all clear on what you mean by the above.
Could you spell it out in greater detail?
This post has been edited by janotte: 22 May 2009 - 11:39 PM
Posted 23 May 2009 - 06:35 AM
Anarion, on 23 May, 2009 - 02:22 AM, said:
my idea is to generate an exe file that has the part-names inside it and when user executes it, the original file is made.
That sounds unnecessarily difficult and unnecessarily restrictive -- it will only be usable on Windows systems. Why not simply generate a text file with a sequential list of the parts, and a function that reads that text file, opens the corresponding files and merges them in order.
Edit: looked again at your splitting function. You could enhance your output-file naming with a counter. i.e., the file extensions could be .part0, .part1, ... Then the merging function only needs to know the filename stem and the number of parts.
This post has been edited by r.stiltskin: 23 May 2009 - 06:44 AM
Posted 03 June 2009 - 08:10 AM
Quote I'm really not at all clear on what you mean by the above.
Could you spell it out in greater detail?
I meant something like the way self-extractors work, but as "r.stiltskin" said, creating a text file with the names is way better, sorry with my bad idea, i just wanted to make it with less number of files. 
thanks for telling me about it
Quote Edit: looked again at your splitting function. You could enhance your output-file naming with a counter. i.e., the file extensions could be .part0, .part1, ... Then the merging function only needs to know the filename stem and the number of parts.
the code already creates them using the format you mentioned.
Posted 15 June 2009 - 10:14 AM
I came into this problem: i re-wrote some parts of the code to make an exe file with instructions to merge the file, i wrote and compiled the code for merger app which reads data from the end of itself, and it works properly. but when i run the merger exe which is newly created with data at the end of it, and when i run it, it gives me errors that it cant be run.
void kfs(string in_name, long int max) {
stringstream sfename;
fstream in(in_name.c_str(), ios::binary|ios::in|ios::ate);
if(in.is_open()) {
long int fsize = in.tellg();
in.seekg(0, ios::beg);
long int r = fsize, p;
int i = 0;
char * buffer = new char[BUFFER_SIZE+1];
fstream out;
fstream inst("toc.tmp", ios::out);
if(inst.is_open()) {
inst<<in_name<<";";
int len = in_name.length();
while(max <= r) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
out.open(sfename.str().c_str(), ios::out|ios::binary);
p = max;
if(out.is_open()) {
while(p>=BUFFER_SIZE) {
in.read(buffer, BUFFER_SIZE);
out.write(buffer, BUFFER_SIZE);
p -= BUFFER_SIZE;
}
if(p>0) {
in.read(buffer, p);
out.write(buffer, p);
}
}
out.close();
inst<<sfename.str().c_str()<<";";
sfename.str("");
r -= max;
}
if(r>0) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
out.open(sfename.str().c_str(), ios::out|ios::binary);
if(out.is_open()) {
p=r;
while(p>=BUFFER_SIZE) {
in.read(buffer, BUFFER_SIZE);
out.write(buffer, BUFFER_SIZE);
p -= BUFFER_SIZE;
}
if(p>0) {
in.read(buffer, p);
out.write(buffer, p);
}
}
out.close();
inst<<sfename.str().c_str();
sfename.str("");
}
in.close();
inst.close();
}
delete[] buffer;
ifstream toc_in("toc.tmp", ios::binary|ios::ate);
ifstream merger_in("merger_data.exe", ios::binary|ios::ate);
string m_name = "merge_" + in_name + ".exe";
ofstream merger_out(m_name.c_str(), ios::binary);
if(toc_in.is_open() && merger_in.is_open() && merger_out.is_open()) {
int toc_len = toc_in.tellg();
int merger_len = merger_in.tellg();
char * toc_data = new char[toc_len+1];
char * merger_data = new char[merger_len+1];
if(toc_data && merger_data) {
merger_in.read(merger_data, merger_len);
merger_out.write(merger_data, merger_len);
toc_in.read(toc_data, toc_len);
merger_out.write(toc_data, toc_len);
} else {
cout<<"Error Allocating Memory!"<<endl;
}
delete[] toc_data; delete[] merger_data;
} else {
cout<<"Cannot read file!"<<endl;
}
toc_in.close();
merger_in.close();
merger_out.close();
system("del toc.tmp");
}
}
Whta do i have to do ? im totally lost in this.
Posted 15 June 2009 - 03:36 PM
are you just trying to merge two files?
you can just use the
rdbuf()
function
Posted 15 June 2009 - 05:19 PM
Anarion, on 15 Jun, 2009 - 01:14 PM, said:
I came into this problem: i re-wrote some parts of the code to make an exe file with instructions to merge the file, i wrote and compiled the code for merger app which reads data from the end of itself, and it works properly. but when i run the merger exe which is newly created with data at the end of it, and when i run it, it gives me errors that it cant be run.
...
Whta do i have to do ? im totally lost in this.
First, please rewrite the above because I don't understand what you are trying to say, and as nobody else has offered an answer I'm guessing that I'm not the only one.
It might be helpful to post the error messages as well.
Posted 16 June 2009 - 03:29 AM
OK, the function "kfs" must do these things: it will split the file into parts with the given size whch it does correct now. other thing it must do is to copy the merger program's exe file and add a TOC at the end of it. this TOC data will have the original file's name which we split and also it contains the part names (like fname;fname.part1;fname.part2;).
But after this function does it's job, when i run the newly created exe, it comes up with error.
do i need to do anything special or is my code wrong ?
Posted 16 June 2009 - 03:30 PM
A Windows .exe file is a compiled, executable program. Your merge_[in_name].exe is (I guess) a string made up of multiple filenames, or something like that. (Sorry, I don't have the time or patience now to study it in detail.) But what I'm sure of is that it's not a program and that's why the OS is telling you it's not runnable.
Calling it "ios::binary" and naming it ".exe" doesn't make it a program. It's still just a text file in disguise. You know what a program is -- since you're writing one, right?
As I told you a few weeks ago, you can easily write a program that takes a list of files as its input, and merges those files. Then your splitter program just has to write a file containing the list of names of the split files it produced, and the merger program can use that file of names to re-merge them.
If you insist on having an executable that has the partial-file list built-in, then you can write a splitter program that does all of these things:
1a. writes a text file containing the complete source-code for the merger program, including the list of partial-file names (as, say, an array of strings)
2. closes that output file
3. compiles the merger source code, presumably using a system call to run the compiler
Posted 18 June 2009 - 02:45 AM
 Thanks for spending time for replying, I already made an individual program that reads from the end of itself like this:
[binary data of exe file which reads from itself][custom data]
this was how it must work... i tweaked the code a bit and now it runs ok and can read the first part of the custom data which is the original file's name. But when it must read the file-parts' names, it reads empty. so my program wants to read from the file "" and that's very wrong. i don't know what i did wrong
Code for Merger Application which must read data from it's end:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void kfm(string, int);
string getToc(char * file);
int main(int argc, char * argv[]) {
string toc = getToc(argv[0]);
kfm(toc, 10);
system("pause");
return 0;
}
string getToc(char * file) {
char * toc;
string stoc;
ifstream self(file, ios::binary|ios::ate);
if(self.is_open()) {
long int end = self.tellg();
long int i = end;
char c = ' ';
cout<<"Reading TOC..."<<endl;
while(c != '|' && i>=0) {
i -= 1;
self.seekg(i);
self.read(&c, 1);
}
int len = end-i;
cout<<"TOC Length: "<<len<<" bytes"<<endl;
toc = new char[len+1];
if(toc) {
self.read(toc, len);
stoc.assign(toc);
delete[] toc;
} else {
cout<<"Allocation error"<<endl;
}
} else {
cout<<"Cannot open self!"<<endl;
}
self.close();
return stoc;
}
void kfm(string toc, int buffer_size) {
int ii = toc.find_first_of(';', 0); int i=0;
string fname = toc.substr(i, ii-i);
ofstream out(fname.c_str(), ios::binary);
if(out.is_open()) {
string pn;
ifstream pin;
char * data_block = new char[buffer_size+1];
data_block[buffer_size] = '\0';
if(data_block) {
long int psize, r;
while(ii<toc.length()) {
i = ii;
ii = toc.find_first_of(';', i);
pn = toc.substr(i, ii-i);
pin.open(pn.c_str(), ios::binary|ios::ate);
if(pin.is_open()) {
psize = pin.tellg();
pin.seekg(0, ios::beg);
// USE BUFFERED METHOD
if(psize > buffer_size) {
r = psize;
while(r>=buffer_size) {
pin.read(data_block, buffer_size);
data_block[buffer_size] = '\0';
out.write(data_block, buffer_size);
r -= buffer_size;
}
if(r>0) {
pin.read(data_block, r);
data_block[r] = '\0';
out.write(data_block, r);
}
// USE NORMAL METHOD
} else {
pin.read(data_block, psize);
out.write(data_block, psize);
}
pin.close();
} else {
cout<<"Cannot read from the file \""<<pn<<"\""<<endl;
break;
}
}
delete[] data_block;
} else {
cout<<"Cannot Allocate Memory"<<endl;
}
} else {
out.close();
cout<<"Cannot create the file \""<<fname<<"\""<<endl;
}
}
This is the program which splits the file and creates the merger_[in_name].exe:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
const int MB = 1048576;
const int KB = 1024;
const int GB = 1073741824;
const int BUFFER_SIZE = 10;
void kfs(string in_name, long int max);
long int calc_size(char * in);
int main() {
/* GET INPUT FILE NAME */
string fname;
cout<<"Enter file's name: ";
getline(cin, fname);
/* GET MAXIMUM SIZE OF PARTS */
char * maxc = new char[12];
maxc[11] = '\0';
cout<<"Enter maximum size allowed: ";
cin.getline(maxc, 11);
long int max = calc_size(maxc);
delete[] maxc;
/* SPLIT THE FILE */
kfs(fname, max);
system("pause");
return 0;
}
long int calc_size(char * in) {
int i; long int s; char c;
for(i=0; i<=10; i++) {
c = in[i];
if(c=='k' || c=='K' || c=='m' || c=='M' || c=='g' || c=='G') {
break;
}
}
string in2 = in;
in2.substr(0, i-1);
s = strtol(in2.c_str(), NULL, 10);
if(c=='k' || c=='K') {
s *= KB;
} else if(c=='m' || c=='M') {
s *= MB;
} else if(c=='g' || c=='G') {
s *= GB;
}
return s;
}
void kfs(string in_name, long int max) {
stringstream sfename;
fstream in(in_name.c_str(), ios::binary|ios::in|ios::ate);
if(in.is_open()) {
long int fsize = in.tellg();
in.seekg(0, ios::beg);
long int r = fsize, p;
int i = 0;
char * buffer = new char[BUFFER_SIZE+1];
fstream out;
fstream inst("toc.tmp", ios::out);
if(inst.is_open()) {
inst<<"|"<<in_name<<";";
int len = in_name.length();
while(max <= r) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
out.open(sfename.str().c_str(), ios::out|ios::binary);
p = max;
if(out.is_open()) {
while(p>=BUFFER_SIZE) {
in.read(buffer, BUFFER_SIZE);
out.write(buffer, BUFFER_SIZE);
p -= BUFFER_SIZE;
}
if(p>0) {
in.read(buffer, p);
out.write(buffer, p);
}
}
out.close();
inst<<sfename.str().c_str()<<";";
sfename.str("");
r -= max;
}
if(r>0) {
i++;
sfename<<in_name.substr(0, len-4)<<".part"<<i;
out.open(sfename.str().c_str(), ios::out|ios::binary);
if(out.is_open()) {
p=r;
while(p>=BUFFER_SIZE) {
in.read(buffer, BUFFER_SIZE);
out.write(buffer, BUFFER_SIZE);
p -= BUFFER_SIZE;
}
if(p>0) {
in.read(buffer, p);
out.write(buffer, p);
}
}
out.close();
inst<<sfename.str().c_str()<<';';
sfename.str("");
}
in.close();
inst.close();
}
delete[] buffer;
ifstream toc_in("toc.tmp", ios::binary|ios::ate);
ifstream merger_in("merger_data.exe", ios::binary|ios::ate);
string m_name = "merge_" + in_name + ".exe";
ofstream merger_out(m_name.c_str(), ios::binary);
if(toc_in.is_open() && merger_in.is_open() && merger_out.is_open()) {
int toc_len = toc_in.tellg();
toc_in.seekg(0, ios::beg);
int merger_len = merger_in.tellg();
merger_in.seekg(0, ios::beg);
char * toc_data = new char[toc_len+1];
char * merger_data = new char[merger_len+1];
if(toc_data && merger_data) {
merger_in.read(merger_data, merger_len);
merger_out.write(merger_data, merger_len);
merger_out.close();
toc_in.read(toc_data, toc_len);
ofstream m_out(m_name.c_str(), ios::binary|ios::ate|ios::app);
if(m_out.is_open()) {
m_out.write(toc_data, toc_len);
m_out.close();
} else {
cout<<"Cannot Open file "<<m_name.c_str()<<endl;
}
} else {
cout<<"Error Allocating Memory!"<<endl;
}
delete[] toc_data; delete[] merger_data;
} else {
cout<<"Cannot read file!"<<endl;
}
toc_in.close();
merger_in.close();
merger_out.close();
system("del toc.tmp");
}
}
Posted 18 June 2009 - 06:57 AM
Very clever. It never occurred to me that you could add text to the end of an executable file.
Well, getTOC works correctly. Are you sure that the file splitter program is actually appending the file list?
Posted 18 June 2009 - 10:41 AM
Well, actually the base idea was not mine, I read it on the internet that people do that for self-extracting exe files. Then I thought I can use this for my application to make it easier to use it.
I am 90% sure that the filesplitter program writes them correctly because I can read the original file's name from the exe file. I am checking it over again...
Posted 18 June 2009 - 11:37 AM
In
while(ii<toc.length()) {
i = ii;
ii = toc.find_first_of(';', i);
pn = toc.substr(i, ii-i);
on the second line, shouldn't ii be ii+1? Otherwise, doesn't it keep "refinding" the same ';'?
Posted 18 June 2009 - 02:37 PM
hahaha good point!  THANKS  actually i found this some hours ago myself but there is another problem when i write ii+1. there will be an extra loop which wants to read another file and outputs it cannot read the file "" but actually the program does it's job correct at least. what do i have to do in order to fix that ?
I have even rewrote that part like this:
while(ii<toc.find_last_of(';', 0)) {
i = ii+1;
still i got that output but the program merges files correct
Posted 18 June 2009 - 03:00 PM
I'm not positive about this, but try:
while(ii<toc.length()) {
i = ii;
// from this point on, the rest of the while block executes only if; is found
if( (ii = toc.find_first_of(';', i)) != string::npos ) {
pn = toc.substr(i, ii-i);
pin.open(pn.c_str(), ios::binary|ios::ate);
if(pin.is_open()) {
psize = pin.tellg();
pin.seekg(0, ios::beg);
// USE BUFFERED METHOD
if(psize > buffer_size) {
r = psize;
while(r>=buffer_size) {
pin.read(data_block, buffer_size);
data_block[buffer_size] = '\0';
out.write(data_block, buffer_size);
r -= buffer_size;
}
if(r>0) {
pin.read(data_block, r);
data_block[r] = '\0';
out.write(data_block, r);
}
// USE NORMAL METHOD
} else {
pin.read(data_block, psize);
out.write(data_block, psize);
}
pin.close();
} else {
cout<<"Cannot read from the file \""<<pn<<"\""<<endl;
break;
}
}
}
1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users
|
Be Social
Programming
Web Development
Reference Sheets
Bye Bye Ads
Monthly Drawing
Top Contributors
Top 10 Kudos This Month
|