Researched by Ed Ort
Release 1.0
June 2001
Question
How do I calculate the number of bytes in a MIDP input stream over an HTTP
connection?
I have to store these bytes in an array for storing the data in a RMS
RecordStore. My current way is to allocate an array with 1024 bytes and
fill it until no more data can be read. This means, I do something like this:
HttpConnection connection =
(HttpConnection)Connector.open("http://www.test.com");
InputStream inputStream = connection.openInputStream();
byte[] byteArray = new byte[1024];
int oneByte = inputStream.read();
int length = 0;
while (oneByte != -1) {
byteArray[length] = (byte)oneByte;
oneByte = inputStream.read();
length++;
}
|
That's not what I want. The biggest problem with this solution is that I am limited
to the actual size of the array (1024 bytes in this case). Even when I can ensure
that my byte stream never exceeds this limit, I still allocate 1024 bytes -- even
when I only need 100 bytes.
The implementation of the available() method in InputStream
always returns 0 (as the API documentation describes it). So that isn't
a solution either.
Tip
Try the following:
HttpConnection connection = (HttpConnection)
Connector.open("http://www.test.com/servlet/readData");
InputStream inputStream = connection.openDataInputStream();
int length = connection.getLength();
byte[] byteArray;
if (length == -1) {
// Reading from an HTTP 1.0 server or a chunked HTTP 1.1
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c ;
while (true) {
c = inputStream.read();
if (c == -1)
break;
baos.write(c);
}
byteArray = baos.getBytes();
} else {
// Reading a Content-Length labeled payload
byteArray = new byte[length];
inputStream.readFully(byteArray);
}
|
In HTTP you can test the Content-Length header. If the length is not provided, you
may be dealing with an HTTP 1.0 server. A simple ByteArrayOuputStream
can be used locally to accumulate the intermediate results.
If the request is delivered using HTTP 1.1 chunked payloads, then the bytes
available() will reflect the current payload contents that can
be read without blocking. This works because the chunked encoding is run-length
encoded, for example, a length is sent and then the implementation sends that number
of bytes to an internal buffer. Calls to read, simply move the bytes from the
internal buffer into the user's buffer without actually talking to the socket
connection.
However, if the web server does not set the Content-Length header and is not using
chunked encoding, then the only way to calculate the number of bytes returned is to
read bytes until the stream is closed. That's all you can do: if no length is set,
then HTTP requires the server to send the bytes and to then close its end of the
stream. So you have to read all the data, buffer it, and count the length once it's
done reading.
There are two ways you can determine whether the web server does not set the
Content-Length header. You can use getLength() and check for a value of
-1; getLength() returns a -1 to indicate that the length is not known.
Or you can get the "Content-Length" header and check for a null return
value.
Note that a client application can force HTTP 1.0 behavior by including
the "Connection: close" header. In this behavior, the server closes the
socket when it is done with the request.
For applications that make multiple round trip requests to the same server,
you can achieve the best performance by taking advantage of the HTTP 1.1 persistent
connections. This is particularly true if the requests are made over real wireless
networks where the bandwidth is slow and the latency is very high.
More Information
Acknowledgments
Many thanks to Eric Giguere for contributing to this answer.
 |
 |
 |
 |
 |
Note: If you have a question to which you need an answer, try the Wireless Forums. You can read through the existing topics, or with your free Wireless membership, you can post new messages or threads.
|
 |
 |
 |
Back To Top
|