PDA

View Full Version : readrawdata' s read size



yagabey
21st January 2008, 09:25
Hello friends,

I am trying to send serial data over com port. i am using qextserialport for serialport communication.

I thought that most suitable way for me is to use QDatastream . As below, when i clicked the send button, some part(1944 bytes ) of avatar.png is sent.

I say "some part of" ; because for the values more than 1944, i get an error about memcpy. I tried this on another machine; this time instead of 1944, at most 1976 bytes were being send without an error..

What is the problem with it?


void MainWindow::on_sendButton_clicked()
{
QFile file("C:/avatar.png");
QDataStream out(&file);

if (!file.open(QIODevice::ReadOnly)) {
cerr << "Cannot open file for writing: "
<< qPrintable(file.errorString()) << endl;
return;
}

char *datas = new char();
out.readRawData(datas,1944);
sp->send(1944,datas);
}

marcel
21st January 2008, 10:22
It's pretty obvious:


char* datas = new char();
allocates a SINGLE char. So it would crash no matter on what machine you run it. It depends on how much the heap is fragmented. In your particular case, there was an unallocated hole of 1944 bytes starting at the address pointed to by datas.

You should read the file in buffers.

yagabey
21st January 2008, 10:52
Thanks Marcel,

But valid arguements for readRawData are (char * s, int len) , how will read a buffer into QDatastream..
and also my send function (actually write(const char *data, qint64 len) ) has arguements : const char *data, qint64 len

How can i adopt all these?
I am a new programmer , so be tolerant toward me :)

marcel
21st January 2008, 11:00
Try this:


int maxSize = 1024;
char* datas = new char[maxSize];
while(!out->atEnd())
{
int actuallyRead = out.readRawData(datas, maxSize);
sp->send(actuallyRead, datas);
}
delete[] datas;

yagabey
21st January 2008, 11:59
Ok thanks, it works correctly now!..

yagabey
21st January 2008, 12:38
A small qestion more:

How can this code progress to the next 1024 bytes, after reading first 1024. Does atEnd() do it for us?




int maxSize = 1024;
char* datas = new char[maxSize];

while(!out->atEnd()) //checks the end of file
{
int actuallyRead = out.readRawData(datas, maxSize); //counts read bytes
sp->send(actuallyRead, datas); //send the data
}
delete[] datas;

marcel
21st January 2008, 12:55
No, readRawData advances the iodevice marker.

yagabey
21st January 2008, 13:18
Hmmm ok I got it...

in the datalistener side, i used a similar code:


void MainWindow::dataListener()
{
int maxSize = 1024;
char *buffer = new char[maxSize];
QFile file("C:/imgreceived.GIF");
QDataStream in(&file);

if (!file.open(QIODevice::WriteOnly)) {
cerr << "Cannot open file for writing: "
<< qPrintable(file.errorString()) << endl;
return;
}

while(1){
int rec=sp->receive(maxSize,buffer);
in.writeRawData(buffer,rec);
if(rec != maxSize)
break;
}

}

This works correctly but i doubt using that break condition :if(rec != maxSize), because the last record may also be 1024 bytes(low possiblity;but perhaps :))

How else i can end writing to the file ?

marcel
21st January 2008, 13:30
QExtSerialPort is a QIODevice so you can still use atEnd to test if there's something to read.

yagabey
21st January 2008, 14:04
do you mean something like:


while(!sp->atEnd()){
int rec=sp->receive(maxSize,buffer);
in.writeRawData(buffer,rec);
}
didn't work but i used bytesavailable()>0 it is ok now..


while(sp->bytesavailable()>0){
int rec=sp->receive(maxSize,buffer);
in.writeRawData(buffer,rec);
}

wysota
21st January 2008, 14:59
QExtSerialPort is a QIODevice so you can still use atEnd to test if there's something to read.

QExtSerialPort is a sequencial device so atEnd() will probably not work properly.

marcel
21st January 2008, 15:05
QExtSerialPort is a sequencial device so atEnd() will probably not work properly.
Seems so...

yagabey
21st January 2008, 15:50
Any other way to decide end of reception?

wysota
21st January 2008, 16:57
The protocol you use should be able to send an "end of stream" marker or send the expected stream length at the beginning of the transmission. There are no ways of indicating the end of transmission on the transportation layer, because you might always write some more data into the stream.

yagabey
22nd January 2008, 07:40
Is there anybody who can show me a sample code for datalistener side? It is working problemeatic ... First 4 kb of the data is being read; but the rest not !

The datalistener is connected to a signal which is emitted when bytesAvailable()>0.

On the serialport monitor, I observed that; first alll of the data is being sent and after that on the datalistener side, this mass data is being read. I mean; it is like a half duplex communiction; reading and writing are not simultaneous...May this be the cause for the problem?