Send file length with outputstream and receive length and byte[] with inputstream for streaming frames from one device to the other Android/Java

I have searched and searched and everything I have found has been helpful but I keep getting an out of memory error. The images I send are .06 MB so I know the problem isn't from decoding the byte[] into a bitmap. When I remove the while loops this works like a charm for one frame but I want multiple frames. I am getting a byte[] and sending it to a different device using sockets but I am at a loss how to do this. My problem is that I don't send and receive the correct byte[] length. This is what i am doing currently.

while (count != -1) {

     //first send the byte[] length
     dataOutputStream.writeInt(sendPackage.length);

     //pass a byte array
     publishProgress("sending file to client");
     showMyToastOnUiThread(String.valueOf(sendPackage.length));
     outputStream.write(sendPackage, 0, sendPackage.length);
     outputStream.flush();
}

Receive byte[] on different device:

int count = inputStream.read();
while (count != -1) {
     int byteArrayLength = dataInputStream.readInt();
     Log.i(MainActivity.TAG, "Starting convert to byte array");

     byte[] receivedBytes = convertInputStreamToByteArray(inputStream, byteArrayLength);

     Bitmap bitmap = BitmapFactory.decodeByteArray(receivedBytes, 0, receivedBytes.length);
     publishProgress(bitmap);
}

//convert inputstream to byte[]
    public byte[] convertInputStreamToByteArray(InputStream inputStream, int readLength) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] data = new byte[readLength];
        try {

            Log.i(MainActivity.TAG, "Starting convert to byte array while loop");
            int readTotal = 0;
            int count = 0;

            while (count >= 0 && readTotal < readLength) {
                count = inputStream.read(data, readTotal, readLength - readTotal);
                if (readLength > 0) {
                    readTotal += count;
                }
            }

            Log.i(MainActivity.TAG, "Finished convert to byte array while loop");

        } catch (IOException e) {
            Log.e(MainActivity.TAG, "error: " + e.getMessage());
            e.printStackTrace();
        }
        return data;
    }
Jon Skeet
people
quotationmark

This is the problem:

int count = inputStream.read();
while (count != -1) {

You're consuming a byte and then ignoring it. That means the next value you read (the size) will be incorrect. You need a different way of telling whether you're at the end of the stream. Some options:

  • Send a -1 when you're finished; that way you can stop as soon as readInt returns -1
  • If you know it, send the number of images you're going to send before you start sending them
  • Use mark(1), then read(), then reset() - if your stream supports marking. I don't know whether it will or not. You could always wrap it in BufferedInputStream if not.
  • Reimplement DataInputStream.readInt yourself in a way which detects the end of the stream as being an expected possibility instead of throwing an exception
  • Just catch an exception in readInt (not nice - getting to the end of the stream isn't really exceptional)

people

See more on this question at Stackoverflow