"Hej, Amigo! Idag ska vi återigen gräva i hur InputStream och OutputStream fungerar. Den initiala förklaringen var faktiskt lite förenklad. Det här är inga gränssnitt. De är abstrakta klasser, och de har till och med ett par implementerade metoder. Låt oss ta en titt på de metoder de har:"

InputStream-metoder Vad metoden gör
int read(byte[] buff);
Den här metoden läser omedelbart in ett block av byte i bufferten ( byte array ), tills bufferten är full eller tills källan inte har några fler byte att läsa.
Metoden returnerar antalet byte som faktiskt lästs (vilket kan vara mindre än längden på arrayen)
int read();
Denna metod läser en byte och returnerar den. Resultatet breddas till en int för utseende. Om det inte finns fler byte att läsa returnerar metoden -1.
int available();
Denna metod returnerar antalet olästa (tillgängliga) byte.
void close();
Denna metod "stänger" strömmen. Du kallar detta när du är klar med strömmen.
Objektet utför sedan de hushållningsoperationer som behövs för att stänga filen etc.
Vid det här laget kan du inte läsa mer data från strömmen.

"Så vi kan läsa inte bara enstaka byte, utan också hela block?"

"Exakt."

"Kan vi också skriva hela block?"

"Ja, kolla upp det:"

OutputStream-metoder Vad metoden gör
void write(int c);
Denna metod skriver en byte. Int-typen är begränsad till en byte. Den extra delen kasseras helt enkelt.
void write(byte[] buff);
Denna metod skriver ett block av byte.
void write(byte[] buff, int from, int count);
Denna metod skriver en del av ett block av byte. Det används i fall då byte-arrayen kanske inte har fyllts helt.
void flush();
Om strömmen internt lagrar data som ännu inte har skrivits, tvingar den här metoden att skrivas.
void close();
Denna metod "stänger" strömmen. Du kallar detta när du är klar med strömmen.
Objektet utför sedan de hushållningsoperationer som behövs för att stänga filen, etc. Du kan inte längre skriva data till strömmen och tömning anropas automatiskt.

"Hur skulle filkopieringskoden se ut om vi läser hela block åt gången istället för enstaka byte?"

"Hmm. Något så här:"

Kopiera en fil på disken
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();
}

"Jag förstår allt om bufferten, men vad är denna räknevariabel?"

"När vi läser det senaste datablocket från en fil kan vi få, säg, 328 byte istället för 1000. Så när vi skriver data måste vi indikera att vi inte skriver hela blocket - bara de första 328 bytes."

När vi läser det sista blocket kommer läsmetoden att returnera antalet byte som faktiskt lästs. 1000 varje gång vi läser ett block, förutom det sista blocket, då vi får 328.

Så när vi skriver ett block indikerar vi att inte alla byte i bufferten ska skrivas, bara 328 (dvs värdet lagrat i räknevariabeln).

"Nu är allt klart. Tack, Ellie."