CodeGym /Java blogg /Slumpmässig /Ingång/utgång i Java. klasserna FileInputStream, FileOutp...
John Squirrels
Nivå
San Francisco

Ingång/utgång i Java. klasserna FileInputStream, FileOutputStream och BufferedInputStream

Publicerad i gruppen
"Hej! I dagens lektion kommer vi att fortsätta vårt samtal om in- och utdataströmmar i Java ( Java I/O ). Detta är inte den första lektionen om detta ämne, och det kommer definitivt inte att vara den sista :) Ingång/utgång i Java.  Klasserna FileInputStream, FileOutputStream och BufferedInputStream - 1Eftersom det händer ger Java-språket många sätt att arbeta med I/O. Det finns en hel del klasser som implementerar denna funktionalitet, så vi har delat upp dem i flera lektioner — så att du inte blir förvirrad från början :) Tidigare lektioner, vi berörde BufferedReader, liksom de InputStreamabstrakta OutputStreamklasserna och flera ättlingar. Idag ska vi överväga 3 nya klasser: , FileInputStream,  FileOutputStreamoch  BufferedInputStream.

Klassen FileOutputStream

Huvudsyftet med FileOutputStreamklassen är att skriva bytes till en fil. Inget komplicerat :) FileOutputStreamär en av implementeringarna av den OutputStreamabstrakta klassen. I konstruktorn tar objekt av denna klass antingen sökvägen till målfilen (där byte ska skrivas) eller ett Fileobjekt. Vi kommer att undersöka exempel på var och en:

public class Main { 

   public static void main(String[] args) throws IOException { 

       File file = new File("C:\\Users\\Username\\Desktop\\test.txt"); 
       FileOutputStream fileOutputStream = new FileOutputStream(file); 

       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
}
När vi skapade Fileobjektet skickade vi den önskade sökvägen till konstruktorn. Vi behöver inte skapa det i förväg: om det inte finns kommer programmet att skapa det. Du kan också klara dig utan att skapa ett extra objekt, bara skicka en sträng med sökvägen:

public class Main { 

    public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
Resultatet i båda fallen blir detsamma. Vi kan öppna vår fil och se följande där:

Hi! Welcome to CodeGym — The best site for would-be programmers!
Men det finns en nyans här. Prova att köra koden från exemplet ovan flera gånger i rad. Titta sedan i filen och svara på denna fråga: hur många rader har den? Bara en. Men du körde koden flera gånger. Det visar sig att data skrivs över varje gång - den gamla ersätts av den nya. Vad gör vi om det inte passar oss och vi behöver skriva sekventiellt till filen? Tänk om vi vill skriva en hälsning till en fil tre gånger i rad? Det hela är väldigt enkelt. Eftersom språket inte kan veta vilket beteende vi behöver i varje enskilt fall, FileOutputStreamkan konstruktören ta en extra parameter —boolean append. Om dess värde är sant kommer data att skrivas till slutet av filen. Om det är falskt (och som standard är det falskt), kommer alla gamla data att raderas och ersättas med nya data. Låt oss kontrollera detta genom att köra vår modifierade kod tre gånger:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true); 
       String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n"; 

       fileOutputStream.write(greetings.getBytes()); 
       fileOutputStream.close(); 
   } 
} 
Filinnehåll:

Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers! 
Hi! Welcome to CodeGym — The best site for would-be programmers!
Nu är det annorlunda! Glöm inte den här funktionen när du använder I/O-klasser. Det fanns en tid då jag spenderade timmar på uppgifter, tjafsade i timmar, försökte förstå hur min data försvann från filer :) Och naturligtvis, precis som med andra I/O-klasser, glöm inte att använda close()metoden att frigöra resurser.

Klassen FileInputStream

Den FileInputStreamhar det motsatta syftet - att läsa bytes från en fil. Precis som FileOutputStreamärver härstammar OutputStreamdenna klass från den InputStreamabstrakta klassen. Vi kommer att skriva några rader text i vår " test.txt "-fil:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Ingång/utgång i Java.  Klasserna FileInputStream, FileOutputStream och BufferedInputStream - 2Så här ser det ut att läsa data från en fil med FileInputStream:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       int i; 

       while((i=fileInputStream.read())!= -1){ 

           System.out.print((char)i); 

       } 
   } 
}
Vi läser en byte från filen, konverterar de lästa byten till tecken och visar dem på konsolen. Och här är konsolutgången:

So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters

Klassen BufferedInputStream

Jag tror, ​​med tanke på kunskapen från tidigare lektioner, att du enkelt kan säga varför vi behöver klassen BufferedInputStreamoch vilka fördelar den har jämfört med FileInputStream:) Vi har redan stött på buffrade strömmar, så försök gissa (eller kom ihåg) innan du fortsätter läsa :) Buffertade strömmar behövs främst för att optimera I/O. Att komma åt en datakälla, som att läsa från en fil, är en dyr operation i termer av prestanda och att komma åt en fil för att läsa varje byte är slöseri. Det är därför som BufferedInputStreamläser data inte en byte åt gången, utan i block, och lagrar dem tillfälligt i en speciell buffert. Detta låter oss optimera programmet genom att minska antalet gånger vi får åtkomst till filen. Låt oss se hur det här ser ut:

public class Main { 

   public static void main(String[] args) throws IOException { 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt"); 

       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200); 

       int i; 

       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 
   } 
} 
Här skapade vi ett BufferedInputStreamobjekt. Dess konstruktor tar en instans av InputStreamklassen eller någon av dess avkomlingar, så FileInputStreamkommer att göra det. Som ett ytterligare argument tar den buffertstorleken i byte. Tack vare detta argument kommer data nu att läsas från filen inte en byte åt gången, utan 200 byte åt gången! Föreställ dig hur mycket vi har minskat antalet filåtkomster. För att jämföra prestanda kan du ta en stor textfil (flera megabyte text) och jämföra hur lång tid det tar i millisekunder att läsa och mata ut till konsolen med FileInputStreamoch BufferedInputStream. Här är kod som visar båda alternativen:

public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf"); 
       BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 

       int i; 
       while((i = bufferedInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 

       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   } 
} 

 
public class Main { 

   public static void main(String[] args) throws IOException { 

       Date date = new Date(); 
       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf"); 

       int i; 
       while((i = fileInputStream.read())!= -1){ 

           System.out.print((char)i); 
       } 


       Date date1 = new Date(); 
       System.out.println((date1.getTime() - date.getTime())); 
   }
}
När jag läste en 1,5 MB fil på min dator, FileInputStreamslutförde arbetet på ~3500 millisekunder, men BufferedInputStreamklarade det på ~1700 millisekunder. Som du kan se optimerade den buffrade strömmen arbetet och halverade det! :) Vi kommer att fortsätta att studera I/O-klasser — vi ses snart!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION