"Ciao, Amigo! Oggi approfondiremo ancora una volta come funzionano InputStream e OutputStream . La spiegazione iniziale era in realtà un po' semplicistica. Queste non sono interfacce. Sono classi astratte e hanno anche un paio di metodi implementati. Diamo un'occhiata ai metodi che hanno:"

Metodi InputStream Cosa fa il metodo
int read(byte[] buff);
Questo metodo legge immediatamente un blocco di byte nel buffer ( array di byte ), finché il buffer non è pieno o finché l'origine non ha più byte da leggere.
Il metodo restituisce il numero di byte effettivamente letti (che può essere inferiore alla lunghezza dell'array)
int read();
Questo metodo legge un byte e lo restituisce. Il risultato viene ampliato a un int per i look. Se non ci sono più byte da leggere, il metodo restituisce -1.
int available();
Questo metodo restituisce il numero di byte non letti (disponibili).
void close();
Questo metodo «chiude» il flusso. Lo chiami quando hai finito di lavorare con lo stream.
L'oggetto quindi esegue le operazioni di pulizia necessarie per chiudere il file, ecc.
A questo punto, non è possibile leggere altri dati dallo stream.

"Quindi possiamo leggere non solo singoli byte, ma anche interi blocchi?"

"Esattamente."

"Possiamo scrivere anche blocchi interi?"

"Sì, dai un'occhiata:"

Metodi OutputStream Cosa fa il metodo
void write(int c);
Questo metodo scrive un byte. Il tipo int è ristretto a un byte. La parte extra viene semplicemente scartata.
void write(byte[] buff);
Questo metodo scrive un blocco di byte.
void write(byte[] buff, int from, int count);
Questo metodo scrive parte di un blocco di byte. Viene utilizzato nei casi in cui l'array di byte potrebbe non essere stato riempito completamente.
void flush();
Se il flusso memorizza internamente dati che non sono ancora stati scritti, questo metodo ne forza la scrittura.
void close();
Questo metodo «chiude» il flusso. Lo chiami quando hai finito di lavorare con lo stream.
L'oggetto quindi esegue le operazioni di pulizia necessarie per chiudere il file, ecc. Non è più possibile scrivere dati nel flusso e flush viene chiamato automaticamente.

"Come sarebbe il codice di copia del file se leggessimo interi blocchi alla volta invece di singoli byte?"

"Hmm. Qualcosa del genere:"

Copia un file su disco
public static void main(String[] args) throws Exception
{
 //Create a stream to read bytes from a file
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 //Create a stream to write bytes to a file
 FileOutputStream outputStream = new FileOutputStream("c:/result.txt");

  byte[] buffer = new byte[1000];
 while (inputStream.available() > 0) //as long as there are unread bytes
 {
  //Read the next block of bytes into buffer, and store the actual number of bytes read in count.
  int count = inputStream.read(buffer);
  outputStream.write(buffer, 0, count); //Write a block (part of a block) to the second stream
 }

 inputStream.close(); //Close both streams. We don't need them any more.
 outputStream.close();
}

"Capisco tutto sul buffer, ma cos'è questa variabile count?"

"Quando leggiamo l'ultimo blocco di dati da un file, potremmo ottenere, diciamo, 328 byte invece di 1000. Quindi, quando scriviamo i dati, dobbiamo indicare che non stiamo scrivendo l'intero blocco, ma solo i primi 328 byte."

Quando leggiamo l'ultimo blocco, il metodo read restituirà il numero di byte effettivamente letti. 1000 ogni volta che leggiamo un blocco, ad eccezione dell'ultimo blocco, quando otteniamo 328.

Quindi, quando scriviamo un blocco, indichiamo che non devono essere scritti tutti i byte nel buffer, solo 328 (cioè il valore memorizzato nella variabile count).

"Adesso è tutto chiaro. Grazie, Ellie."