2010-09-12 11 views
41

Cosa fa InputStream.available() in Java? Ho letto la documentazione, ma non riesco ancora a capirlo.Che cosa fa InputStream.available() in Java?

Il dottore dice:

Restituisce il numero di byte che possono essere letti (o saltato) da questo flusso di input senza bloccare dalla prossima chiamante di un metodo per questo flusso di input. Il prossimo chiamante potrebbe essere lo stesso thread o un altro thread.

Il metodo disponibile per la classe InputStream restituisce sempre 0.

cosa si intende per bloccando? Significa solo una chiamata sincronizzata?

E soprattutto, qual è lo scopo del metodo available()?

+1

Ci sono pochissimi usi veramente utili di available(). Uno di questi è per la lettura da System in. – EJP

risposta

24

Il blocco non riguarda la filettatura o la sincronizzazione qui. Invece si riferisce al blocco dell'IO (vedi this per maggiori informazioni). Se si invia una richiesta di lettura e il canale non ne ha, una chiamata di blocco attenderà (o bloccherà) finché i dati non saranno disponibili (o il canale è chiuso, genera un'eccezione ecc.)

Quindi perché utilizzare available()? In questo modo puoi determinare quanti byte leggere o determinare se stai per bloccare.

Si noti che Java ha anche capacità di IO non bloccanti. Vedere here per ulteriori dettagli

+0

Mi sono imbattuto in questa domanda e ora mi sto chiedendo, posso usare available() per risolvere il mio problema, senza ricorrere a NIO. La mia domanda: http://stackoverflow.com/questions/3867042/one-thread-per-client-doable –

+6

Questa risposta non è corretta. Una chiamata di blocco si bloccherà mentre sono disponibili * non * dati. Se chiedi quattro e ce ne sono tre, ne ottieni tre. – EJP

+0

Ora è corretto, grazie Brian. – EJP

30

In InputStreams, le chiamate read() sono chiamate di metodo "bloccanti". Ciò significa che se non ci sono dati disponibili al momento della chiamata al metodo, il metodo attenderà che i dati siano resi disponibili.

Il metodo available() indica quanti byte possono essere letti fino a quando la chiamata read() bloccherà il flusso di esecuzione del programma. Sulla maggior parte dei flussi di input, tutte le chiamate a read() stanno bloccando, ecco perché disponibile restituisce 0 per impostazione predefinita.

Tuttavia, su alcuni flussi (ad esempio BufferedInputStream, che dispongono di un buffer interno), alcuni byte vengono letti e conservati in memoria, quindi è possibile leggerli senza bloccare il flusso del programma. In questo caso, il metodo available() indica quanti byte sono conservati nel buffer.

+7

BufferedInputStream.available() indica quanti byte possono essere letti senza bloccare. Questa è la * somma * del numero di byte già presenti nel buffer e il risultato avaiable() del flusso di input annidato. Nota anche che available() restituisce sempre zero per un socket SSL. – EJP

+0

Quello che non ho capito è quello che è * l'uso * di saperlo. Davvero, non riesco a capire perché dovrei preoccuparmi, cioè non riesco a vedere dove e quando in mu app potrei trovarlo utile. Certo, è abbastanza ovvio che io sia ignorante, ma questo è dovuto alla mia * mancanza * di esperienza. –

+0

Come ho detto sopra, ci sono pochissimi usi utili. Devi sapere che hai a che fare con uno stream che fornirà una risposta diversa da zero e quindi devi usarla per il risultato. – EJP

-2

Considerare se si scrive software MOLTO CATTIVO .. e si scrive un sistema operativo.

Questo sistema operativo accetta l'input da tastiera, tra le altre cose.

Così chiedete al sistema operativo di andare e ottenere un input da tastiera, ma non ci sono tasti premuti e nessuno nel buffer. l'intero sistema operativo HANG DEAD finché non riceve un input da tastiera.

Contrasto con "guarda avanti", chiedi se il KB ha caratteri PRIMA di effettuare la chiamata. Si ottiene la risposta NO, quindi il sistema operativo va e fa qualcos'altro.

Questo è PERCHÉ dovresti preoccuparti, ora se poi lo moltiplichi per ogni altro compito potenzialmente bloccante, puoi capire perché 'guardare avanti' è fondamentale.

Perché si applica anche a OUTPUT: una memoria su un'interfaccia dell'unità disco può anche inondare i dati sull'unità disco più rapidamente di quanto non possa elaborarli. se non si sa che il buffer dell'unità è inondato di dati, l'attività bloccherà fino a quando il buffer non potrà accettare più dati.

Ciò evidenzia anche il non senso di "ci sono pochissimi usi utili".

+0

No, non lo è. Non stavo parlando di scrivere software molto male; Non stavo parlando di scrivere sistemi operativi; Non stavo parlando di scrivere su un'interfaccia drive-disk: 'available()' non ti aiuta con la scrittura. Stavo parlando di 'InputStream.available()' in *** Java, *** che era multithreading l'ultima volta che ho guardato. L'unico esempio valido che date qui è lo stesso dell'eccezione che ho menzionato: la lettura dalla tastiera. – EJP

-2

Uno dei possibilmente pratico utilizza available() per scegliere una lunghezza del buffer ragionevole.

static final int LEN = 4096; 

long copy(InputStream in, OutputStream out) throws IOException { 
    int count = 0L; 
    int avl = in.available(); 
    if (avl == 0) { 
     // 0 returned without IOException? possibly mean eof? 
     return 0L; 
    } 
    //byte[] buf = new byte[avl == 0 ? LEN : Math.min(avl, LEN)]; 
    byte[] buf = new byte[Math.min(avl, LEN)]; 
    for (int len; (len = in.read(buf)) != -1; count+= len) { 
     out.write(buf, 0, len); 
    } 
    return count; 
} 

Il documento dice,

Reso: una stima del numero di byte che possono essere letti (o saltati) da questo flusso di input senza bloccare o 0 quando raggiunge la fine del flusso di input.

E

Una sottoclasse implementazione di questo metodo può scegliere di lanciare un IOException se questo flusso di input è stato chiuso richiamando il metodo close().

UPDATE

so già l'idea non è raccomandato. Ho conosciuto questo rischio anche prima che il documento di JDK lo avvertisse. (Una volta ho provato a allocato un buffer dalla available di qualche GB dimensioni FileInputStream.)

JDK8/InputStream#available

Non è mai corretto usare il valore di ritorno di questo metodo per allocare un buffer destinato a contenere tutti i dati in questo flusso.

JDK5/InputStream#availabe

Ma, nella programmazione, non ci dovrebbero nessun codice never o always wrong. Questo è quello che sto credendo.

+1

No, no e no. Leggi la javadoc. "Non è mai corretto utilizzare il valore restituito da questo metodo per allocare un buffer destinato a contenere tutti i dati in questo flusso." – Grod

+0

@Gordon Ho già letto la javadoc. Ed è per questo che ho detto * possibilmente-pratico * e ho usato 'Math # min'. –

+1

Parola chiave "MAI". Non importa se pensi che sia "possibilmente-pratico". Non usarlo in questo modo. Supponiamo di avere 16777216 byte (16 MiB) da leggere. 'available()' potrebbe restituire 4 nel momento in cui hai assegnato il buffer. Ora hai assegnato un buffer da 4 byte e il ciclo verrà eseguito 4194304 volte. Quando il javadoc dice "mai", significa NON FARLO. – Grod