CodeGym /Blog Java /Aleatoriu /Intrare/ieșire în Java. Clasele FileInputStream, FileOutp...
John Squirrels
Nivel
San Francisco

Intrare/ieșire în Java. Clasele FileInputStream, FileOutputStream și BufferedInputStream

Publicat în grup
„Bună! În lecția de astăzi, vom continua conversația despre fluxurile de intrare și ieșire în Java ( Java I/O ). Aceasta nu este prima lecție pe acest subiect și, cu siguranță, nu va fi ultima Intrare/ieșire în Java.  Clasele FileInputStream, FileOutputStream și BufferedInputStream - 1:) se întâmplă, limbajul Java oferă multe modalități de a lucra cu I/O. Există destul de multe clase care implementează această funcționalitate, așa că le-am împărțit în mai multe lecții - astfel încât să nu fii confundat de la început :) În trecut lecții, am atins BufferedReader, precum și clasele InputStreamși OutputStreamabstracte și mai mulți descendenți. Astăzi vom lua în considerare 3 clase noi: FileInputStream,  FileOutputStream, și  BufferedInputStream.

Clasa FileOutputStream

Scopul principal al FileOutputStreamclasei este de a scrie octeți într-un fișier. Nimic complicat :) FileOutputStreameste una dintre implementările OutputStreamclasei abstracte. În constructor, obiectele acestei clase iau fie calea către fișierul țintă (unde ar trebui să fie scrii octeții), fie un Fileobiect. Vom examina exemple din fiecare:

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(); 
   } 
}
La crearea Fileobiectului, am trecut calea dorită către constructor. Nu trebuie să-l creăm în prealabil: dacă nu există, programul îl va crea. De asemenea, vă puteți descurca fără a crea un obiect suplimentar, pur și simplu trecând un șir cu calea:

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(); 
   } 
} 
Rezultatul în ambele cazuri va fi același. Putem deschide fișierul nostru și vedem următoarele acolo:

Hi! Welcome to CodeGym — The best site for would-be programmers!
Dar există o nuanță aici. Încercați să rulați codul din exemplul de mai sus de mai multe ori la rând. Apoi uită-te în fișier și răspunde la această întrebare: câte rânduri are? Doar unul. Dar ai rulat codul de mai multe ori. Se dovedește că datele sunt suprascrise de fiecare dată - cele vechi sunt înlocuite cu cele noi. Ce facem dacă nu ni se potrivește și trebuie să scriem secvențial în fișier? Ce se întâmplă dacă vrem să ne scriem salutul într-un fișier de trei ori la rând? Totul este foarte simplu. Deoarece limbajul nu poate ști ce comportament avem nevoie în fiecare caz, constructorul FileOutputStreampoate lua un parametru suplimentar -boolean append. Dacă valoarea sa este adevărată, datele vor fi scrise la sfârșitul fișierului. Dacă este fals (și implicit este fals), orice date vechi vor fi șterse și înlocuite cu date noi. Să verificăm acest lucru rulând codul nostru modificat de trei ori:

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(); 
   } 
} 
Conținutul fișierului:

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!
Acum asta e diferit! Nu uitați de această caracteristică atunci când utilizați clase I/O. A fost o perioadă în care mi-am petrecut ore în șir cu sarcini, mi-am bătut mintea ore în șir, încercând să înțeleg cum îmi dispăreau datele din fișiere :) Și bineînțeles, la fel ca și în cazul altor clase de I/O, nu uitați să folosiți close()metoda pentru a elibera resurse.

Clasa FileInputStream

Are FileInputStreamscopul opus - citirea octeților dintr-un fișier. La fel cum FileOutputStreammoștenește OutputStream, această clasă derivă din InputStreamclasa abstractă. Vom scrie câteva rânduri de text în fișierul nostru „ test.txt ”:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Intrare/ieșire în Java.  Clasele FileInputStream, FileOutputStream și BufferedInputStream - 2Iată cum arată să citești date dintr-un fișier folosind 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); 

       } 
   } 
}
Citim un octet din fișier, convertim octeții citiți în caractere și îi afișăm pe consolă. Și iată rezultatul consolei:

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

Clasa BufferedInputStream

Cred că, având în vedere cunoștințele din lecțiile anterioare, puteți spune cu ușurință de ce avem nevoie de BufferedInputStreamclasă și ce avantaje are în comparație cu FileInputStream:) Am întâlnit deja fluxuri tamponate, așa că încercați să ghiciți (sau să vă amintiți) înainte de a continua să citiți :) Fluxurile tamponate sunt necesare în principal pentru a optimiza I/O. Accesarea unei surse de date, cum ar fi citirea dintr-un fișier, este o operațiune costisitoare din punct de vedere al performanței, iar accesarea unui fișier pentru a citi fiecare octet este o risipă. De aceea BufferedInputStreamcitește datele nu câte un octet, ci în blocuri și le stochează temporar într-un buffer special. Acest lucru ne permite să optimizăm programul prin reducerea numărului de ori accesăm fișierul. Să vedem cum arată asta:

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); 
       } 
   } 
} 
Aici am creat un BufferedInputStreamobiect. Constructorul său ia o instanță a InputStreamclasei sau oricare dintre descendenții acesteia, așa FileInputStreamva face. Ca un argument suplimentar, este nevoie de dimensiunea tamponului în octeți. Datorită acestui argument, datele vor fi citite acum din fișier nu câte un octet, ci câte 200 de octeți la un moment dat! Imaginează-ți cât de mult am redus numărul de accesări la fișiere. Pentru a compara performanța, puteți lua un fișier text mare (câțiva megaocteți de text) și puteți compara cât timp durează, în milisecunde, citirea și trimiterea către consolă folosind FileInputStreamși BufferedInputStream. Iată codul care demonstrează ambele opțiuni:

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())); 
   }
}
Când am citit un fișier de 1,5 MB pe computerul meu, FileInputStreamam finalizat munca în ~3500 milisecunde, dar BufferedInputStreamam reușit-o în ~1700 milisecunde. După cum puteți vedea, fluxul tamponat a optimizat lucrul, reducându-l la jumătate! :) Vom continua să studiem cursurile I/O — ne vedem în curând!
Comentarii
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION