I'm working on a project where I'm downloading packets of data over internet and parsing them in my application. Every packet has it's own structure and in the beginning I'm receiving only text data. But in some point I start to get binary packets with images and this kind of stuff and sometimes on some devices when the binary file is too big I'm getting this error. Actually it's never happend while I'm testing, but I'm getting some reports from users. Here is actually how I'm doing it :
reading response :
InputStream response = new BufferedInputStream(connection.getInputStream());
int bytesRead = -1;
byte[] buffer = new byte[30 * 1024];
while ((bytesRead = response.read(buffer)) > 0 && stopThread) {
byte[] buffer2 = new byte[bytesRead];
System.arraycopy(buffer, 0, buffer2, 0, bytesRead);
handleDataFromSync(buffer2);
}
and parsing the data like this :
public void handleDataFromSync(byte[] buffer) {
RPCPacket packet;
String responseBody;
while(!stopThread) return;
try {
responseBody = new String(buffer, "UTF-8");
StringBuilder tmp = new StringBuilder(responseBody);
totalBytesReceived += responseBody.length();
if (tmpBuffer != null) {
tmpBuffer = tmpBuffer.append(tmp);
tmp = tmpBuffer;
}
int bufferLen = tmp.length();
int lastLoc = 0;
boolean gotPacket;
boolean gotField;
String thisPart = "";
try {
do {
gotPacket = false;
gotField = true;
int needsSize = packetFieldSizes[tmpCurrentField - 1];
if (tmpCurrentField == packetFieldSizes.length) {
needsSize = payloadSize;
}
if (needsSize > bufferLen - lastLoc) {
gotField = false;
String proba = tmp.substring(lastLoc);
tmpBuffer = new StringBuilder(proba);
break;
}
thisPart = tmp.substring(lastLoc, lastLoc + needsSize);
lastLoc += needsSize;
if (gotField) {
switch (tmpCurrentField) {
case 1: {
long intVal = Long.parseLong(thisPart);
objectIdentificator = (int) intVal;
break;
}
case 2: {
long intVal = Long.parseLong(thisPart);
if (intVal == 0) {
isBad = true;
break;
}
pType = (short) intVal;
break;
}
case 3: {
long intVal = Long.parseLong(thisPart);
if (intVal == 0) {
isBad = true;
break;
}
operationType = (short) intVal;
break;
}
case 4: {
objectOId = thisPart;
break;
}
case 5: {
long intVal = Long.parseLong(thisPart);
if (intVal == 0) {
isBad = true;
break;
}
id = (int) intVal;
break;
}
case 6: {
long intVal = Long.parseLong(thisPart);
payloadSize = (int) intVal;
dataSize = (int) intVal;
break;
}
case 7: {
hashH = thisPart;
break;
}
case 8: {
long intVal = Long.parseLong(thisPart);
if (intVal == 0) {
isBad = true;
break;
}
dataType = (short) intVal;
break;
}
case 9: {
if (payloadSize != 0) {
byte[] tmpData = Base64.decode(thisPart);
first = tmpData;
}
break;
}
}
if (tmpCurrentField >= packetFieldSizes.length)
gotPacket = true;
if (gotPacket) {
Log.d("", "Gotpacket!");
packet = new RPCPacket(objectIdentificator,
RPCPacketType.getPacketTypeByValue(pType),
RPCOperationType.getByValue(operationType),
objectOId, id, dataSize, hashH,
RPCPacketDataType.getByValue(dataType),
first);
parseRPCPacket(packet);
myProgress++;
update();
Log.e("","myProgress : "+myProgress);
Log.e("","TOTAL PACKETS : "+RPCCommunicator.totalPackets);
// release temp fields
objectIdentificator = 0;
pType = 0;
operationType = 0;
objectOId = null;
id = 0;
dataSize = 0;
hashH = null;
dataType = 0;
first = null;
tmpCurrentField = 1;
payloadSize = 0;
} else {
tmpCurrentField++;
}
}
// you baad bad buffer
assert (lastLoc <= bufferLen);
if (isBad)
break;
} while (true);
} catch (IOException e) {
e.printStackTrace();
RPCCommunicator.writeLogs(e.toString(), "Synchronization" ,"handleDataFromSync");
} finally {
thisPart = null;
tmp = null;
}
} catch (Exception e) {
e.printStackTrace();
RPCCommunicator.writeLogs(e.toString(), "Synchronization","handleDataFromSync");
}
}
so the error is thrown in that line : tmpBuffer = tmpBuffer.concat(tmp); only when the image is too big and it's concatenating the string a few times to get the whole packet. I'm reading response in 30KB pieces, but I can receive images with 300, 400KB and etc.
So any kind of idea how can I get rid of this issue. I'm not really sure what can I use instead of this.
Thanks in advance!
StringBuilder(orStringBuffer) instead of using Strings. Are you concat:ing the binary stuff into yourtmpvariable also?resposeBody