Click to See Complete Forum and Search --> : How to format my output using ofstream


diehardii
January 20th, 2004, 11:31 PM
Hi, I have a quick question on formatting.

I am writing a program that takes a buffer of type char* and writes it to a logfile via

logfile << (unsigned int*)bufffer1[i];


Unfortunately, the output is always in the format

0x000000E00x0000001F0x0000001E0x00000081

I would like to put it into the format

E0 1F 1E 81

but I can't figure out how to do it with ofstream. The code is below and kind of quick and dirty. I have thousands of these strings to look at, so if anyone has any idea I'd greatly appreciate it. Thanks for your time.

~Steve

// Compares a nonfunctional mpeg and the same file made functional
#include <fstream.h>
#include <iomanip>

const char * file1 = "test.mpeg";
const char * file2 = "testcorrected.mpeg";


int main ()
{
unsigned char *buffer1;
unsigned char *buffer2;
unsigned char *buffer3;
long size1;
long size2;
long tot_byteoffsets = 0;
ifstream file1 (file1, ios::in | ios::binary | ios::ate);
ifstream file2 (file2, ios::in|ios::binary|ios::ate);
size1 = file1.tellg();
size2 = file2.tellg();
file1.seekg (0, ios::beg);
file2.seekg(0, ios::beg);
buffer1 = new unsigned char [size1];
buffer2 = new unsigned char [size2];
buffer3 = new unsigned char [size1];
file1.read(buffer1, size1);
file2.read(buffer2, size2);
file1.close();
file2.close();

// Setup log file
ofstream logfile("logfile.txt");

logfile << "Starting log \n\n" ;


cout << "the complete file is in a buffer" << endl;
cout << "The file size is " << size1 << endl;
cout << "Starting compare" << endl;

//Main comparison loop
int i = 0;
int j = 0;

while (i < size1)
{
if(buffer1[i] == buffer2[j])
{
buffer3[j] = buffer1[i];
i++;
j++;
}
else
{
int bytechange = 0;
logfile << "The following string differs at byte offset " << i << endl;
while((buffer1[i] != buffer2[j]) || (buffer1[i+1] != buffer2[j+1]) ||
(buffer1[i+2]!= buffer2[j+2]))
{
bytechange++;

logfile << (unsigned int*) buffer1[i];
if (bytechange%4 == 0)
logfile << " ";
i++;
}

logfile << "\nTotal bytes - " << bytechange<< endl << endl;

//j++;
tot_byteoffsets += bytechange;
buffer3[j] = buffer1[i];
}


}

//write mpegfile based on comparison
ofstream myFile ("output.mpeg", ios::out | ios::binary);
myFile.write(buffer3,(size1-tot_byteoffsets));

cout << "Total kilobytes difference is " << (tot_byteoffsets/1024) << endl;



delete[] buffer1;
delete[] buffer2;
delete[] buffer3;
return 0;
}

nsh123
January 20th, 2004, 11:38 PM
if you write in binary file the output will be written in binary form as is the case here.

Regards

diehardii
January 20th, 2004, 11:42 PM
Hi,

The ofstream is not flagged as anything, and the data has to be read into binary for the ifstream but if I do

logfile.hex

the output is the same. Thanks for the hand, do you know how to fix this.

~Steve

TDM
January 21st, 2004, 01:08 AM
Hi,

The pointer is not required for the unsigned int cast.

logfile<<setbase(16)<<(unsigned int)buffer1[i]<<" ";

Here is some of the output from the log file.

Starting log

The following string differs at byte offset 36
bd 29 40 8 40 4c 1b d9 b e0 2b c4 5a 8e 0 bc 84 82 4a 18 4a 51 50.................

You really need to add checks in your code and make sure it won't result in access violations, particularly in the while loops. I have a feeling that this is a school assignment...am I correct?

TDM

treuss
January 21st, 2004, 03:34 AM
This problem had me freak out for quite some time. The problem imho, that the standard c++ library does not make any difference in the implementation of:

ostream& operator<<( const char );
ostream& operator<<( const unsigned char);

while I believe it should take the first as a character and the second as a short short int.

Here is how I finally solved it. Consider the string s to contain binary data (yes, c++ strings can contain binary data without problems). The "& 0xff" thing might be a bit hacky, but it was what got the whole thing working.


void hexdump( ostream& o, const string& s )
{
// save the current state of o
const ios::fmtflags old_flags = o.flags();
o << hex;
for ( unsigned long i = 0; i < s.length(); ++i )
o << setw(2) << setfill('0') << (s[i] & 0xff) << ' ';
// restore the old state of o
o.setf( old_flags );
}

diehardii
January 21st, 2004, 07:49 AM
Hi TDM,
Its not a school assignment, I'm just not very good with byte streams. I bought a Creative DVCR TV card, and I shouldn't have skimped ...

It writes a non-standard MPEG stream, that when multiplexed can't be read by windows MPEG demultiplexers. However I found and old MS demultiplexer that I was able to modify to work. Unfortunately, it is very difficult to read the code for the parser, so I am taking the test mpeg stream, running it through the demultiplexer and dumping the output to file. I believe the rules to be easy (and preliminary analysis suggests they are), so this is my way of seeing them. Once I figure out the rules, I'll be able to finish my Directshow filter and be able to write a compliant mpeg2 stream from my (now worthless) card. Thanks for all of your help.

~Steve

P.S. There aren't any violations, although for a more general program, I agree it would be a good idea.

treuss
January 21st, 2004, 08:56 AM
Looking at the other posts, I am now wondering why I am having such problems with putting out a hexdump of a std::string. Can anybody explain me why the following code

const unsigned char data[] = { 0, 127, 128, 255 };
for ( unsigned int i = 0; i < 4; ++i )
cout << setbase(16) << (unsigned int)data[i] << ' ';
cout << endl;

const string s( (char*)data, 4 );
for ( unsigned int i = 0; i < 4; ++i )
cout << setbase(16) << (unsigned int)s[i] << ' ';
cout << endl;

gives the following output

0 7f 80 ff
0 7f ffffff80 ffffffff

Thanks for enlightenment.