CodeGym /Java blog /Véletlen /Bemenet/kimenet Java nyelven. FileInputStream, FileOutput...
John Squirrels
Szint
San Francisco

Bemenet/kimenet Java nyelven. FileInputStream, FileOutputStream és BufferedInputStream osztályok

Megjelent a csoportban
"Sziasztok! A mai leckében a Java bemeneti és kimeneti adatfolyamairól folytatjuk a beszélgetést ( Java I/O ). Nem ez az első lecke ebben a témában, és biztosan nem is az utolsó Bemenet/kimenet Java nyelven.  FileInputStream, FileOutputStream és BufferedInputStream osztályok – 1:) Előfordul, hogy a Java nyelv számos módot biztosít az I/O-val való munkavégzéshez. Jó néhány osztály valósítja meg ezt a funkciót, ezért ezeket több leckére osztottuk – így nem fog összezavarodni a kezdetektől :) leckéket érintettünk BufferedReader, valamint a InputStreamés OutputStreamabsztrakt osztályokat és több leszármazottat. Ma 3 új osztályt fogunk figyelembe venni: FileInputStream,  FileOutputStream, és  BufferedInputStream.

A FileOutputStream osztály

Az osztály fő célja, FileOutputStreamhogy bájtokat írjon egy fájlba. Semmi bonyolult :) FileOutputStreamaz absztrakt osztály egyik implementációja OutputStream. A konstruktorban ennek az osztálynak az objektumai vagy a célfájl elérési útját (ahova a bájtokat kell írni), vagy egy Fileobjektumot követnek. Megvizsgálunk mindegyikre példákat:

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(); 
   } 
}
Az objektum létrehozásakor Filea kívánt útvonalat adtuk át a konstruktornak. Nem kell előre elkészítenünk: ha nem létezik, akkor a program elkészíti. Azt is megteheti, hogy nem hoz létre extra objektumot, egyszerűen átad egy karakterláncot az elérési úttal:

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(); 
   } 
} 
Az eredmény mindkét esetben ugyanaz lesz. Megnyithatjuk a fájlunkat, és ott a következőket láthatjuk:

Hi! Welcome to CodeGym — The best site for would-be programmers!
De van itt egy árnyalat. Próbálja meg többször egymás után futtatni a fenti példából származó kódot. Ezután nézze meg a fájlt, és válaszoljon erre a kérdésre: hány soros? Csak egy. De többször lefuttatta a kódot. Kiderült, hogy az adatokat minden alkalommal felülírják – a régit felváltja az új. Mit tegyünk, ha ez nem felel meg nekünk, és sorban kell írnunk a fájlba? Mi van akkor, ha háromszor egymás után szeretnénk egy fájlba írni az üdvözletünket? Minden nagyon egyszerű. Mivel a nyelv nem tudhatja, hogy minden esetben milyen viselkedésre van szükségünk, a FileOutputStreamkonstruktor további paramétert vehet fel:boolean append. Ha az értéke igaz, az adatok a fájl végére íródnak. Ha hamis (és alapértelmezés szerint hamis), minden régi adat törlődik, és új adatokkal helyettesítik. Ellenőrizzük ezt úgy, hogy háromszor futtassuk le módosított kódunkat:

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(); 
   } 
} 
Fájl tartalma:

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!
Ez most más! Ne feledkezzünk meg erről a funkcióról I/O osztályok használatakor. Volt idő, amikor órákat töltöttem feladatokkal, órákig törtem az agyamat, próbáltam megérteni, hogyan tűnnek el az adataim a fájlokból :) És persze, ahogy más I/O osztályoknál, ne felejtsd el használni a close()módszert források felszabadítására.

A FileInputStream osztály

Ennek FileInputStreamaz ellenkezője a célja: bájtok olvasása egy fájlból. Csakúgy, mint FileOutputStreamaz öröklődés OutputStream, ez az osztály az absztrakt osztályból származik InputStream. Néhány sornyi szöveget írunk a " test.txt " fájlunkba:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Bemenet/kimenet Java nyelven.  FileInputStream, FileOutputStream és BufferedInputStream osztályok - 2Íme, hogyan néz ki az adatok olvasása egy fájlból a következővel 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); 

       } 
   } 
}
Kiolvasunk egy bájtot a fájlból, az olvasott bájtokat karakterekké alakítjuk és megjelenítjük a konzolon. És íme a konzol kimenete:

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

A BufferedInputStream osztály

Azt hiszem, a korábbi leckékből szerzett ismeretek alapján könnyen meg tudod mondani, hogy miért van szükségünk az BufferedInputStreamosztályra, és milyen előnyei vannak FileInputStream:) Már találkoztunk pufferolt adatfolyamokkal, úgyhogy próbálj meg tippelni (vagy emlékezni), mielőtt folytatod az olvasást :) A pufferelt adatfolyamokra elsősorban az I/O optimalizálásához van szükség. Az adatforrás elérése, például egy fájlból való olvasás, költséges művelet a teljesítmény szempontjából, és a fájl elérése az egyes bájtok olvasásához pazarló. Éppen ezért BufferedInputStreamnem bájtonként, hanem blokkokban olvassa be az adatokat, és átmenetileg egy speciális pufferben tárolja. Ez lehetővé teszi a program optimalizálását azáltal, hogy csökkenti a fájl elérésének számát. Nézzük, hogy néz ki ez:

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); 
       } 
   } 
} 
Itt létrehoztunk egy BufferedInputStreamobjektumot. A konstruktor egy példányt vesz az InputStreamosztályból vagy bármely leszármazottjából, így FileInputStreammegteszi. További argumentumként a puffer méretét veszi fel bájtokban. Ennek az érvelésnek köszönhetően az adatok mostantól nem egyenként, hanem 200 bájtonként kerülnek kiolvasásra a fájlból! Képzeld el, mennyivel csökkentettük a fájlhozzáférések számát. A teljesítmény összehasonlításához készítsen egy nagy szövegfájlt (több megabájt szöveget), és a és gombokkal hasonlítsa össze, mennyi ideig tart ezredmásodpercben az olvasás és a konzolra való FileInputStreamkimenet BufferedInputStream. Íme egy kód, amely bemutatja mindkét lehetőséget:

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())); 
   }
}
Amikor egy 1,5 MB-os fájlt olvastam a számítógépemen, FileInputStreama munkát ~3500 ezredmásodperc alatt végeztem el, de BufferedInputStream~1700 ezredmásodperc alatt sikerült. Mint látható, a pufferelt adatfolyam optimalizálta a munkát, félbevágva azt! :) Folytatjuk az I/O osztályok tanulmányozását – hamarosan találkozunk!
Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION