: : Ok, here's my program. I used to have chars instead of unsigned chars but neither method works. (Also a clarification of the use of chars vs unsigned chars would be greatly appreciated.)
: :
: :
: : #include <iostream.h>
: : #include <conio.h>
: : #include <fstream.h>
: : #include <string.h>
: :
: : bool containsChar(unsigned char *string, char c);
: : int getReps(unsigned char* string, int start);
: : unsigned char* compress(unsigned char* data, long size);
: :
: : int main(int argc, char* argv[])
: : {
: : if (argc != 2)
: : {
: : cout<<"Incorrect Usage...";
: : getch();
: : return 0;
: : }
: :
: : char* file;
: : file = argv[1];
: :
: : cout<<"Opening " <<file <<"..." <<endl;
: : ifstream in(file, ios::binary);
: :
: : if (!in)
: : {
: : cout<<"Couldn't read " <<argv[1] <<".";
: : getch();
: : return 0;
: : }
: :
: : in.seekg(0, ios::end);
: : long filesize = in.tellg();
: : in.seekg(0);
: :
: : unsigned char* data;
: : data = new unsigned char[filesize];
: : in.read(data, filesize);
: : in.close();
: : cout<<"File read." <<endl;
: :
: : unsigned char* cdata;
: : cout<<"Compressing..." <<endl;
: : cdata = compress(data, filesize);
: : cout<<"Compressed." <<endl;
: :
: : delete [] data;
: :
: : cout<<"Writing compressed file..." <<endl;
: : ofstream out("output.cpr", ios::binary);
: : if (!out)
: : {
: : cout<<"Couldn't open output.cpr.";
: : getch();
: : return 0;
: : }
: : out.write(cdata, strlen((char*)cdata));
: : out.close();
: : cout<<"Done.";
: :
: : delete [] cdata;
: :
: : getch();
: : return 0;
: : }
: :
: : bool containsChar(unsigned char *string, char c)
: : {
: : int size = strlen((char*)string);
: :
: : for (int i=0; i<size; i++)
: : {
: : if (*(string+i) == c)
: : return true;
: : }
: :
: : return false;
: : }
: :
: : int getReps(unsigned char* string, int start, long size)
: : {
: : int reps = 1;
: : int pos = start;
: :
: : while (*(string+pos) == *(string+pos+1))
: : {
: : pos++;
: : reps++;
: : if (pos == size)
: : break;
: : }
: :
: : return reps;
: : }
: :
: : unsigned char* compress(unsigned char* data, long size)
: : {
: : unsigned char* cdata;
: : cdata = new unsigned char[size];
: : char marker;
: :
: : int ascii = 33;
: : while (containsChar(data, (char)ascii))
: : ascii++;
: : marker = (char)ascii;
: : *cdata = marker;
: :
: : int pos1=0, pos2=1, reps; //first char in cdata is the marker
: :
: : while (pos1 < size)
: : {
: : reps = getReps(data, pos1, size);
: :
: : if (reps < 4)
: : {
: : for (int i=0; i<reps; i++)
: : {
: : *(cdata+pos2) = *(data+pos1);
: : pos1++;
: : pos2++;
: : }
: : }
: : else
: : {
: : if (reps > 255)
: : reps = 255;
: : *(cdata+pos2) = marker;
: : *(cdata+pos2+1) = (unsigned char)reps;
: : *(cdata+pos2+2) = *(data+pos1);
: : pos2 += 3;
: : pos1 += reps;
: : }
: : }
: :
: : return cdata;
: : }
: :
: :
:
: You say that the code works fine on text files, and doesn't work on binar files. That seems logical to me, since you use the strlen-function on the data at some places.
: If the data contains a zero-byte, that is interpreted as the end of the string by strlen(), which is probably not what you want.
: Binary data may (or is even likely to) contain zeroes, text-data don't.
:
:
: Greets,
: Eric Goldstein
:
http://www.gvh-maatwerk.nl
:
:
:
Oh wow, the strlen thing didn't even occur to me with zero bytes, I'll try to change that and see if it helps. Thanks