06-09-2010 07:38 AM
Is there a known issue with read not behaving properly in the latest versions of OS 5?
I have an existing app that works perfectly on all BB devices from OS 4.2.1+ ... except for the devices running the latest releases of OS 5.0.0 when I test on the simulator for OS 5.0.0.604 (generic) I get strange behaviour using the read() method on the InputStream created from an HttpConnection's InputConnection.openInputStream(). The problem only occurs when connecting using deviceside=true. It doesn't affect MDS. What I am seeing is:
read(buffer, index, length) internally fills a 1024 byte buffer with data from the http reply.
it then ignores the first 152 bytes and returns the remaining 872 into the buffer parameter. The returned int value for number of bytes read is correct. i.e. 872.
Subsequent calls to read() return the same 872 bytes again. ... it never advances through the stream to return the rest of the data.
Calling the available() method at any point returns the full length of the http reply (in this case 2685)
In all previous versions of the OS, using the same code it returns all 2685 bytes in a single call to read() ... I'm baffled. Has anyone else seen this behaviour?
Solved! Go to Solution.
06-09-2010 10:32 AM
06-09-2010 01:32 PM
It is possible that the first 152 bytes are response headers, that would make sense, but I would expect that the if they are, then the return value for available() should also skip them.
The pertinent part of the code from my project is:
//DOESNT WORK - read is not advancing through the stream, it just returns bytes 152-1024 of _src._buffer repeatedly.
InputStream _src=_httpConnection.openInputStream();
int available = _src.available();
_buffer = new byte[available];
int len = _src.read(_buffer,0,available);
if (len < available)
{
int readOffset = 0;
while (len >= 0 && len + readOffset < available)
{
readOffset += len;
len = read(_buffer, readOffset, available-readOffset);
}
}
Thanks,
~NN
06-09-2010 05:21 PM
I'm not sure I can follow the logic behind this code. My suggestions:
1. Don't use InputStream.available as it is not required to return anything greater than 0 ever. See the javadocs for the contract of the method.
2. Use a simple loop that invokes InputStream.read() until it returns -1 (end of stream). For example,
_buffer = drain(_httpConnection.openInputStream());
private static byte[] drain(InputStream in) throws IOException {
final ByteArrayOutputStream result = new ByteArrayOutputStream();
final byte[] buf = new byte[512];
int chunkLength;
while ((chunkLength = in.read(buf)) != -1) {
result.write(buf, 0, chunkLength);
}
result.close();
return result.toByteArray();
}
06-10-2010 07:49 AM
I have had similar issues on the 8830, but with a 4.2 or 4.5 O/s
Eventually I changed my read() to read a single byte at a time, rather than a buffer, and that solved
my issue.
If I remember correctly, In my case, I knew the total length, and was reading in chunks,
advancing my offset into the buffer, with the amount of data returned by read(byte[],init,int)
06-10-2010 08:38 AM
Have you given getLength() method a try instead of available() method?
Quote from the doc of getLength() method:
"Returns the length of the content which is being provided. E.g. if the connection is via HTTP, then the value of the content-length header field is returned."
06-10-2010 07:33 PM
I was trying to use available() to figure out how big the buffer byte[] had to be. I guess that was a bad choice.
I tried to replicate the odd behaviour in a sample app, but it didn't work. I'll poke at it some more when I get some spare time and if I can consistently break it, I'll post again then. In the meantime, I got my project working by using single byte reads and content-length.
Thanks for the suggestions everyone!
06-11-2010 04:36 AM