Unites N files into a single file (or separates them back).
This utility can be used together w/ my other post titled "Huffman Data Compression" to enable compression of multiple files.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | //file_uniter.cpp
//Unites N files into a single file (or separates them back).
//FB - 201011301
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
using namespace std;
class str
{
public:
string s;
unsigned int l;
};
int main(int argc, char *argv[])
{
if(argc > 2)
{
cerr<<"Too many arguments!"<<endl;
exit(1);
}
unsigned char uc;
char c;
if(argc == 2)
{
cout<<"File separator mode!"<<endl;
ifstream infile(argv[1],ios::in|ios::binary);
if(!infile)
{
cerr<<"The file "<<argv[1]<<" could not be opened!"<<endl;
exit(1);
}
string s;
unsigned int l,j;
while(true)
{
//get the file name
getline(infile,s);
if(s.empty())
break;
cout<<"file name:"<<s<<endl;
//get the file length
//read 4 bytes and combine them into one 32 bit u. int value
l=0;
j=1;
for(int k=3;k>=0;--k)
{
infile.get(c);
uc=c;
l+=uc*(j<<(8*k));
}
cout<<"size:"<<l<<endl;
ofstream outfile(s.c_str(),ios::out|ios::binary);
if(!outfile)
{
cerr<<"The file "<<s<<" could not be opened!"<<endl;
exit(1);
}
for(unsigned int i=0;i<l;++i)
{
infile.get(c);//cout<<c;
outfile.put(c);
}
//cout<<endl;
outfile.close();
}
infile.close();
}
else //argc == 1
{
cout<<"File uniter mode!"<<endl;
cout<<"Input the file names! (just Enter to end)"<<endl;
vector<str> f_names; //file names
str st;
while(true)
{
getline(cin,st.s);
if(st.s.empty())
break;
ifstream infile(st.s.c_str(),ios::in|ios::binary);
if(!infile)
{
cerr<<"The file "<<st.s<<" could not be opened!"<<endl;
exit(1);
}
//find out the file length (in bytes)
st.l=0;
while(infile.get(c))
{
++st.l;
}
//cout<<"size:"<<st.l<<endl;
infile.clear(); //clear the EOF flag
infile.seekg(0); //reset get() pointer to beginning
infile.close();
f_names.push_back(st);
}
cout<<"Input the output file name:"<<endl;
string s;
cin>>s;
ofstream outfile(s.c_str(), ios::out|ios::binary);
if(!outfile)
{
cerr<<"The file "<<s<<" could not be opened!"<<endl;
exit(1);
}
//output file format: filename1, filelength1, file1, ...
for(unsigned int i=0;i<f_names.size();++i)
{
outfile.write(f_names.at(i).s.c_str(),f_names.at(i).s.size());
//add a next line char to the end of the file name
c='\n';
uc=c;
outfile.put(uc);
//write the file length
//divide 32 bit u. int values into 4 bytes
outfile.put(static_cast<unsigned char>(f_names.at(i).l>>24));
outfile.put(static_cast<unsigned char>((f_names.at(i).l>>16)%256));
outfile.put(static_cast<unsigned char>((f_names.at(i).l>>8)%256));
outfile.put(static_cast<unsigned char>(f_names.at(i).l%256));
//write the file
ifstream infile(f_names.at(i).s.c_str(),ios::in|ios::binary);
for(unsigned int j=0;j<f_names.at(i).l;++j)
{
infile.get(c);
outfile.put(c);
}
infile.clear(); //clear the EOF flag
infile.seekg(0); //reset get() pointer to beginning
infile.close();
}
}//end else
return 0;
}
|
Tags: data_compression
Sample run:
C:\Users\FB\Desktop\file_uniter>file_uniter
File uniter mode!
Input the file names! (just Enter to end)
02.jpg
04.jpg
Input the output file name:
images.pac
C:\Users\FB\Desktop\file_uniter>file_uniter images.pac
File separator mode!
file name:02.jpg
size:115237
file name:04.jpg
size:75676
C:\Users\FB\Desktop\file_uniter>
How can I change this to read all subdirectories