1

I've an Android app which connects to a .NET HTTP service on a PC and allows browsing the media directories on that PC. The interface is similar to a file explorer with a list of current directories / media files.

When a user selects a directory name from the list, the contents of that directory are returned in a JSON response.

My problem is sometimes the Android end of things thinks the JSON is incomplete but I don't know why as I've logged the JSON string at the server end and it is correctly terminated. The Android code that handles the response is as follows...

int contentLength = -1;
int totalRead = 0;
int numRead = -1;

InputStream inStream = connHelper.getInputStream();
contentLength = connHelper.getContentLength();

byte[] buffer = new byte[contentLength != -1 ? contentLength : 8192];
while ((numRead = inStream.read(buffer)) != -1)
    if (numRead != 0)
        totalRead += numRead;

Log.d(TAG, "getMediaList() - totalRead: " + totalRead);
String jsonString = new String(buffer, "UTF-8");
Log.d(TAG, "jsonString.length() - " + jsonString.length());
Log.d(TAG, "jsonString - " + jsonString);

Here's a log from the Android logcat of a good sequence of events...

requestValue: D:\Jukebox\Classical\Classic FM - Smooth Classics (Do Not Disturb) (Disc 2)\
getMediaList() - totalRead: 501
jsonString.length() - 501
jsonString - {"folders":[],"media":[<cut for brevity>]}

...but here's a log of a bad one which is consistent for this list of media...

requestValue: D:\Jukebox\Classical\De Lucia, Paco\Collection\
getMediaList() - totalRead: 353
jsonString.length() - 351
jsonString - {"folders":[],"media":[<cut for brevity>,"14 Concierto de Aranjuez (Adagio).mp3"

Notice the total bytes read for the problem media list is 353 but the jsonString is only 351 bytes. Notice also that the log of jsonString shows the closing array/object characters ]} are missing.

I'm totally confused by this. The .NET server logs show a complete JSON string, the Android logs show 353 bytes are read but the jsonString length shows only 351 bytes. Can anyone explain what might cause this?

Squonk
  • 48,735
  • 19
  • 103
  • 135

2 Answers2

2

I suspect your problem is multi-byte characters coming in from your stream. Especially since you have some non-English filenames in your sample, it's likely that it's getting choked up on some funny character. Rather than converting from your InputStream to bytes to a String, see if you can use an InputStreamReader to handle all that tricky stuff for you.

Argyle
  • 3,324
  • 25
  • 44
  • I suspected that too, but the only missing characters are apparently `]}`. Also, it looks like the constructor he's using is fine, if it really is UTF-8. – Matthew Flaschen Feb 16 '12 at 00:04
  • 1
    @Argyle: I think you may be on to something. Yes, there is UTF-8 handling at both ends but I think I got something wrong on the server when setting content-length. Multi-byte characters would explain it as there is one 'song' in the list which has a diacritic character and might account for two extra bytes. I need to do a quick re-write. – Squonk Feb 16 '12 at 00:12
  • 1
    @Argyle: Thank you for pointing me in the right direction - I've had a chance to review the server-end code and I was reporting Content-Length as number of characters in the media file name rather than the correct multi-byte count - everything is working now with full diacritic character support. I'll look at `InputStreamReader` tomorrow (currently nearly 2am here). Well who would have thought that having an appreciation of Spanish guitar music would have caused such a headache? :D – Squonk Feb 16 '12 at 01:47
  • Glad to help. Put some of that Spanish guitar on your headphones and smooth over the headache. – Argyle Feb 16 '12 at 18:20
1

First, your loop is incorrect, since read is not guaranteed to read the length you requested. If it doesn't, you will just overwrite the beginning of your array.

This doesn't seem to be the issue here, but I would still use the correct loop.

Did you explicitly check what the length on the server is?

Community
  • 1
  • 1
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • You're correct, that's not a good loop - I normally use one similar to the one in your link but had cut it back as I was trying to work things out. You are, however, also correct that this is not the issue. The first (good) example consistently reads 501 bytes and the string is consistently 501 in length. The second consistently reads 353 but the length of the string is 351. The string logged at the server includes the closing `]}` and is exactly 353 bytes. – Squonk Feb 15 '12 at 23:56
  • Thanks again - I have of course reverted to a more sensible loop now the problem is solved. – Squonk Feb 16 '12 at 01:54