PDA

View Full Version : Concatenating two binary files



nbkhwjm
20th April 2007, 16:33
I want to concatenate two binary files.

Basically there is a header file containing a Print Job ticket and a PDF file. I want to put the two together..

Here is what I have..



QFile file("out.prn");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;

The Ticket is obtained and opened read only...



QString ticketName = ticketComboBox->currentText();
QFile *ticket = new QFile(ticketName, ftp);
ticket->open(QIODevice::ReadOnly);
QFileInfo ti( ticketName );

Then the PDF file...


QString fileName = directoryComboBox->currentText();
QFile *file = new QFile(fileName, ftp);
file->open(QIODevice::ReadOnly);
QFileInfo fi( fileName );

My problem is the connection from the Open files and how to dump them into the newly created "out.prn"

Ideas?

marcel
20th April 2007, 16:58
Don't forget that QFile inherits QIODevice:



QFile prnFile;
//
//...Create the output file, etc
//

//first write the ticket
qint64 totalSize = ticket->size();
qint64 chunkSize = 2048; //you can increase it and decrease it as you will

char *readBuffer = new char[chunkSize];
while ( totalSize )
{
if( chunkSize > totalSize )
chunkSize = totalSize;
qint64 actuallyRead = ticket->read( readBuffer, chunkSize );

if( actuallyRead > 0 )
prnFile->write( readBuffer, actuallyRead );
else
break;

totalSize -= actuallyRead;
}
// And when you're done:
delete[] readBuffer;
outPrn.flush();

This is only to write the ticket.
After this you can write the same code to write the pdf file( you must use the same output file, and to make sure, position the file pointer at the end of the file ). Or you can make it a function and call it twice.

For more information you can check QIODevice (http://doc.trolltech.com/latest/qiodevice.html) class description.
Feel free to ask if you have any other questions...

Regards

nbkhwjm
20th April 2007, 18:28
Marel,

Thanks for the pointers this is great.

Im getting an error on running (compiles ok), out.prn is created, but nothing is in it...



QObject: Cannot create children for a parent that is in a different thread.
QObject: Cannot create children for a parent that is in a different thread.



// The Two Files are here.
QString ticketName = ticketComboBox->currentText();
QFile *ticket = new QFile(ticketName, ftp);
ticket->open(QIODevice::ReadOnly);
QFileInfo ti( ticketName );

QString fileName = directoryComboBox->currentText();
QFile *file = new QFile(fileName, ftp);
file->open(QIODevice::ReadOnly);
QFileInfo fi( fileName );

// now put the two files together.



QFile prnFile;

QFile outPrn("out.prn");
if (!outPrn.open(QIODevice::WriteOnly))
return;

//first write the ticket

qint64 totalSize = ticket->size();
qint64 chunkSize = 2048; //you can increase it and decrease it as you will

char *readBuffer = new char[chunkSize];
while ( totalSize )
{
if( chunkSize > totalSize )
chunkSize = totalSize;
qint64 actuallyRead = ticket->read( readBuffer, chunkSize );

if( actuallyRead > 0 )
prnFile.write( readBuffer, actuallyRead );
else
break;
totalSize -= actuallyRead;
// And when you're done:
delete[] readBuffer;
outPrn.flush();
}

//Now Write the PDF file

qint64 ptotalSize = file->size();
qint64 pchunkSize = 2048; //you can increase it and decrease it as you will

char *preadBuffer = new char[pchunkSize];
while ( ptotalSize )
{
if( pchunkSize > ptotalSize )
pchunkSize = ptotalSize;
qint64 pactuallyRead = file->read( preadBuffer, pchunkSize );

if( pactuallyRead > 0 )
prnFile.write( preadBuffer, pactuallyRead );
else
break;
ptotalSize -= pactuallyRead;
// And when you're done:
delete[] preadBuffer;
outPrn.flush();
}

fullmetalcoder
20th April 2007, 19:34
Im getting an error on running (compiles ok), out.prn is created, but nothing is in it...



QObject: Cannot create children for a parent that is in a different thread.
QObject: Cannot create children for a parent that is in a different thread.

Are you running this code within a thread (and especially in the run() method?) If so then you need take care of the parent of you QIODevice... This is a really tricky problem but passing a null pointer to the constructor should do...

marcel
20th April 2007, 20:12
Before everything, check your SRC !!!
Take that delete out of the while! The read buffer should be deleted only one, at the end, when you're done with it.

Regards

nbkhwjm
20th April 2007, 20:12
This function is called as a response to a slot/signal from a SEND button.. The apps comes up , but throws the errors... and now an additonal one...



QObject: Cannot create children for a parent that is in a different thread.
QObject: Cannot create children for a parent that is in a different thread.
*** glibc detected *** double free or corruption (!prev): 0x08b8ad00 ***
*** Process aborted ***


here is the full function...



void Window::sendFile()
{

cancelButton->setEnabled(true);
sendButton->setEnabled(false);
quitButton->setEnabled(false);
browseButton->setEnabled(false);
protocolComboBox->setEnabled(false);
directoryComboBox->setEnabled(false);
printerComboBox->setEnabled(false);

// The Two Files are here.
QString ticketName = ticketComboBox->currentText();
QFile *ticket = new QFile(ticketName, ftp);
ticket->open(QIODevice::ReadOnly);
QFileInfo ti( ticketName );

QString fileName = directoryComboBox->currentText();
QFile *file = new QFile(fileName, ftp);
file->open(QIODevice::ReadOnly);
QFileInfo fi( fileName );

// now put the two files together.
QFile outPrn("out.prn");

//first write the ticket
qint64 totalSize = ticket->size();
qint64 chunkSize = 2048;

char *readBuffer = new char[chunkSize];
while ( totalSize )
{
if( chunkSize > totalSize )
chunkSize = totalSize;
qint64 actuallyRead = ticket->read( readBuffer, chunkSize );

if( actuallyRead > 0 )
outPrn.write( readBuffer, actuallyRead );
else
break;
totalSize -= actuallyRead;

delete[] readBuffer;
outPrn.flush();
}

qint64 ptotalSize = file->size();
qint64 pchunkSize = 2048;

char *preadBuffer = new char[pchunkSize];
while ( ptotalSize )
{
if( pchunkSize > ptotalSize )
pchunkSize = ptotalSize;
qint64 pactuallyRead = file->read( preadBuffer, pchunkSize );

if( pactuallyRead > 0 )
outPrn.write( preadBuffer, pactuallyRead );
else
break;
ptotalSize -= pactuallyRead;
delete[] preadBuffer;
outPrn.flush();
}




ftp = new QFtp(this);

connect(ftp, SIGNAL(stateChanged(int)),
this, SLOT(ftp_stateChanged(int)));

connect(ftp, SIGNAL(commandFinished(int, bool)),
this, SLOT(ftpCommandFinished(int, bool)));


// FTP the final File to the printer here.

}

marcel
20th April 2007, 20:21
Why do you create the QFiles with that ftp object as parent?
Did you know that ftp is not created when you pass it as parent? This is one problem.

As for the crash, I already said, delete the read buffer when you're done with it completely, meaning after you finished copying the pdf file.

I'm sure you get the thread error because ftp has an invalid address when you create the QFiles.

Solution: don't pass the ftp object bas parent to the QFiles. Pass NULL.

Regards

nbkhwjm
20th April 2007, 20:45
I started with an application that would FTP one file to the printer. This worked great..

Then I needed to send two file... so I added a second, but it turned out that i needed to send both files as one...

so looks like i got it...

I appreciate the patience... the issue seems big until you see the problem...

any way this error doesnt seem to cause the app to fail...

QObject: Cannot create children for a parent that is in a different thread.

should i ignore or keep working though it?

marcel
20th April 2007, 20:50
any way this error doesnt seem to cause the app to fail...

QObject: Cannot create children for a parent that is in a different thread.

should i ignore or keep working though it?


I already told you...Pass NULL instead of ftp when you create the QFiles and you will not get this error.

You get this error because the ftp pointer has an invalid adress when you create the QFiles.
At least initialize the pointer to NULL at the beginning of the application.

Regards

nbkhwjm
20th April 2007, 21:03
Marcel,

I completely missed that point, got it....

Thank you very much!!

nbkhwjm
20th April 2007, 21:05
as a Noob to C++, I appreciate your assistance very much!!

marcel
20th April 2007, 21:09
You're welcome

marcel
20th April 2007, 22:15
This is what it should be:


// The Two Files are here.
QString ticketName = ticketComboBox->currentText();
QFile *ticket = new QFile(ticketName, NULL);
ticket->open(QIODevice::ReadOnly);
QFileInfo ti( ticketName );

QString fileName = directoryComboBox->currentText();
QFile *file = new QFile(fileName, NULL);
file->open(QIODevice::ReadOnly);
QFileInfo fi( fileName );

// now put the two files together.
QFile prnFile("out.prn");
if (!outPrn.open(QIODevice::WriteOnly))
return;

//first write the ticket

qint64 totalSize = ticket->size();
qint64 chunkSize = 2048; //you can increase it and decrease it as you will

char *readBuffer = new char[chunkSize];
while ( totalSize )
{
if( chunkSize > totalSize )
chunkSize = totalSize;
qint64 actuallyRead = ticket->read( readBuffer, chunkSize );
if( actuallyRead > 0 )
prnFile.write( readBuffer, actuallyRead );
else
break;
totalSize -= actuallyRead;
}

//Now Write the PDF file
qint64 ptotalSize = file->size();
qint64 pchunkSize = 2048; //you can increase it and decrease it as you will

char *preadBuffer = new char[pchunkSize];
while ( ptotalSize )
{
if( pchunkSize > ptotalSize )
pchunkSize = ptotalSize;
qint64 pactuallyRead = file->read( preadBuffer, pchunkSize );

if( pactuallyRead > 0 )
prnFile.write( preadBuffer, pactuallyRead );
else
break;
ptotalSize -= pactuallyRead;
}

// And when you're done:
delete[] preadBuffer;
prnFile.flush();
delete ticket;
delete file;

nbkhwjm
23rd April 2007, 03:30
Marcel,

I got this to work, Ill compare my code to yours to see how far off I am.. Had all kinds of trouble with a SEG fault in the FTP function, seemed i had a qDebug that was tossing it all...

Thanks for the help...

this is actually getting easier... still painful, but easier...