2014-05-18 12 views
11

Sto provando a effettuare una richiesta a un servizio Web da un'applicazione Android, utilizzando HttpUrlConnection. Ma a volte funziona, ea volte no.DataOutputSteam mi sta gettando un 'java.io.IOException: inaspettato fine del flusso'?

Quando provo l'invio di questo valore:

JSON valore

{"Calle":"Calle Pérez 105","DetalleDireccion":"","HoraPartida":"May 18, 2014 9:17:10 AM","Numero":0,"PuntoPartidaLat":18.477295994621315,"PuntoPartidaLon":-69.93638522922993,"Sector":"Main Sector"} 

ho ricevuto una "fine inaspettata di flusso" Eccezione nella funzione di chiusura DataOutputStream.

Ecco il mio codice:

DataOutputStream printout; 
// String json; 
byte[] bytes; 
DataInputStream input; 

URL serverUrl = null; 
try { 
    serverUrl = new URL(Config.APP_SERVER_URL + URL); 
} catch (MalformedURLException e) { 
    ... 
} 

bytes = json.getBytes(); 
try { 

    httpCon = (HttpURLConnection) serverUrl.openConnection(); 
    httpCon.setDoOutput(true); 
    httpCon.setUseCaches(false); 
    httpCon.setFixedLengthStreamingMode(bytes.length); 
    httpCon.setRequestProperty("Authorization", tokenType + " "+ accessToken); 
    httpCon.setRequestMethod("POST"); 
    httpCon.setRequestProperty("Content-Type", "application/json"); 

    printout = new DataOutputStream(httpCon.getOutputStream()); 
    printout.writeBytes(json); 
    printout.flush(); 
    printout.close(); 
    ... 
} 
+0

potrebbe non riguardare il problema: Se non si desidera utilizzare una * * DataOutputStream esempio. Questo è un formato binario, piuttosto proprietario. Il modo corretto consiste nel convertire la stringa JSON in una matrice di byte utilizzando la codifica UTF-8 e quindi scriverla direttamente nel flusso di output della connessione. – Codo

+0

Un ulteriore problema nel codice è la conversione della stringa JSON in un array di byte utilizzando una codifica predefinita. Quindi si utilizza la lunghezza dell'array per impostare la lunghezza del contenuto. Tuttavia, si applica * DataOutputStream * in un modo in cui la stringa viene scritta in modalità ASCII (writeBytes non utilizza una codifica, ma ignora i bit alti). Quindi potresti avere una mancata corrispondenza tra la lunghezza del contenuto annunciata e quella effettiva. – Codo

risposta

7

Ecco una soluzione con le seguenti modifiche:

  • E si libera del DataOutputStream, che è certamente la cosa sbagliata da usare.
  • Imposta e recapita correttamente la lunghezza del contenuto.
  • Non dipende da alcun valore predefinito relativo alla codifica, ma imposta in modo esplicito UTF-8 in due punti.

Provalo:

// String json; 

URL serverUrl = null; 
try { 
    serverUrl = new URL(Config.APP_SERVER_URL + URL); 
} catch (MalformedURLException e) { 
    ... 
} 

try { 
    byte[] bytes = json.getBytes("UTF-8"); 

    httpCon = (HttpURLConnection) serverUrl.openConnection(); 
    httpCon.setDoOutput(true); 
    httpCon.setUseCaches(false); 
    httpCon.setFixedLengthStreamingMode(bytes.length); 
    httpCon.setRequestProperty("Authorization", tokenType + " "+ accessToken); 
    httpCon.setRequestMethod("POST"); 
    httpCon.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); 

    OutputStream os = httpCon.getOutputStream(); 
    os.write(bytes); 
    os.close(); 

    ... 
} 
+0

Ti amo letteralmente, il problema stava accadendo quando la stringa includeva caratteri accentati come 'í' ma con il tuo approccio funziona come un incantesimo. – Laggel

+1

@Laggel: potrebbe essere dovuto a problemi di codifica? Ad esempio, se viene utilizzata una codifica multibyte come UTF-8, i caratteri accentati generalmente prenderanno più di 1 byte e quindi la lunghezza dei byte rispetto al numero di caratteri non corrisponde più. –

+1

Sì, è per questo che la lunghezza deve essere presa dopo averlo codificato come UTF-8. – Codo

1

Dalla documentazione di Oracle here. Sappiamo che il metodo flush di DataOutputStream chiama il metodo flush del flusso di output sottostante. Se si guarda alla classe URLConnection in here, si dice che ogni sottoclasse di URLConnection deve avere questo metodo sovrascritto. Se vedi HttpUrlConnection here, vediamo che il metodo flush non è sovrascritto. Potrebbe essere una delle ragioni del tuo problema.