CodeGym /Java Blog /Willekeurig /Invoer/uitvoer in Java. FileInputStream-, FileOutputStrea...
John Squirrels
Niveau 41
San Francisco

Invoer/uitvoer in Java. FileInputStream-, FileOutputStream- en BufferedInputStream-klassen

Gepubliceerd in de groep Willekeurig
"Hallo! In de les van vandaag gaan we verder met ons gesprek over invoer- en uitvoerstromen in Java ( Java I/O ). Dit is niet de eerste les over dit onderwerp en het zal zeker niet de laatste zijn Invoer/uitvoer in Java.  FileInputStream-, FileOutputStream- en BufferedInputStream-klassen - 1:) gebeurt, biedt de Java-taal veel manieren om met I/O te werken. Er zijn nogal wat klassen die deze functionaliteit implementeren, dus we hebben ze opgedeeld in verschillende lessen — zodat je vanaf het begin niet in de war raakt :) lessen, we hebben het gehad over BufferedReader, evenals de InputStreamen OutputStreamabstracte klassen en verschillende afstammelingen Vandaag zullen we 3 nieuwe klassen bekijken: FileInputStream,  FileOutputStream, en  BufferedInputStream.

De FileOutputStream-klasse

Het belangrijkste doel van de FileOutputStreamklasse is om bytes naar een bestand te schrijven. Niets ingewikkelds :) FileOutputStreamis een van de implementaties van de OutputStreamabstracte klasse. In de constructor nemen objecten van deze klasse het pad naar het doelbestand (waar de bytes moeten worden geschreven) of een Fileobject. We zullen voorbeelden van elk onderzoeken:

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(); 
   } 
}
Bij het maken van het Fileobject hebben we het gewenste pad doorgegeven aan de constructor. We hoeven het niet van tevoren te maken: als het niet bestaat, zal het programma het maken. Je kunt ook rondkomen zonder een extra object te maken door simpelweg een string met het pad door te geven:

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(); 
   } 
} 
Het resultaat zal in beide gevallen hetzelfde zijn. We kunnen ons bestand openen en daar het volgende zien:

Hi! Welcome to CodeGym — The best site for would-be programmers!
Maar er is hier één nuance. Probeer de code uit het bovenstaande voorbeeld meerdere keren achter elkaar uit te voeren. Kijk dan in het bestand en beantwoord deze vraag: hoeveel regels heeft het? Eentje maar. Maar je hebt de code meerdere keren uitgevoerd. Het blijkt dat de gegevens elke keer worden overschreven - de oude wordt vervangen door de nieuwe. Wat doen we als dat niet bij ons past en we sequentieel naar het bestand moeten schrijven? Wat als we onze begroeting drie keer achter elkaar naar een bestand willen schrijven? Het is allemaal heel eenvoudig. Omdat de taal niet kan weten welk gedrag we in elk geval nodig hebben, FileOutputStreamkan de contrucutor een extra parameter gebruiken —boolean append. Als de waarde waar is, worden de gegevens naar het einde van het bestand geschreven. Als het onwaar is (en standaard is het onwaar), worden alle oude gegevens gewist en vervangen door nieuwe gegevens. Laten we dit controleren door onze gewijzigde code drie keer uit te voeren:

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(); 
   } 
} 
Bestandsinhoud:

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!
Dat is nu anders! Vergeet deze functie niet bij het gebruik van I/O-klassen. Er was een tijd dat ik uren aan taken besteedde, urenlang mijn hersens pijnigde, probeerde te begrijpen hoe mijn gegevens uit bestanden verdwenen :) En natuurlijk, net als bij andere I/O-klassen, vergeet niet om de methode te close()gebruiken middelen vrij te maken.

De FileInputStream-klasse

Het FileInputStreamheeft het tegenovergestelde doel: het lezen van bytes uit een bestand. Net zoals FileOutputStreamerft OutputStream, is deze klasse afgeleid van de InputStreamabstracte klasse. We zullen een paar regels tekst in ons " test.txt " -bestand schrijven:

"So close no matter how far 
Couldn't be much more from the heart 
Forever trusting who we are 
And nothing else matters"
Invoer/uitvoer in Java.  FileInputStream-, FileOutputStream- en BufferedInputStream-klassen - 2Hier hoe het eruit ziet om gegevens uit een bestand te lezen met behulp van 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); 

       } 
   } 
}
We lezen één byte uit het bestand, zetten de gelezen bytes om in tekens en geven ze weer op de console. En hier is de console-uitvoer:

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

De klasse BufferedInputStream

Ik denk dat je, gezien de kennis uit eerdere lessen, gemakkelijk kunt zeggen waarom we de BufferedInputStreamklas nodig hebben en welke voordelen het heeft in vergelijking met FileInputStream:) We zijn al gebufferde streams tegengekomen, dus probeer te raden (of te onthouden) voordat je verder leest :) Gebufferde streams zijn vooral nodig om I/O te optimaliseren. Toegang tot een gegevensbron, zoals het lezen van een bestand, is een dure operatie in termen van prestaties. En toegang tot een bestand om elke byte te lezen is verspilling. Daarom BufferedInputStreamleest data niet byte per keer uit, maar in blokken, en slaat deze tijdelijk op in een speciale buffer. Hierdoor kunnen we het programma optimaliseren door het aantal keren dat we het bestand openen te verminderen. Laten we eens kijken hoe dit eruit ziet:

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); 
       } 
   } 
} 
Hier hebben we een BufferedInputStreamobject gemaakt. De constructor neemt een instantie van de InputStreamklasse of een van zijn afstammelingen, dus dat FileInputStreamzal ook. Als extra argument wordt de buffergrootte in bytes gebruikt. Dankzij dit argument worden de gegevens nu niet byte per keer uit het bestand gelezen, maar met 200 bytes tegelijk! Stelt u zich eens voor hoeveel we het aantal bestandstoegangen hebben verminderd. Om de prestaties te vergelijken, kunt u een groot tekstbestand (enkele megabytes aan tekst) nemen en vergelijken hoe lang het duurt in milliseconden om te lezen en uit te voeren naar de console met behulp van FileInputStreamen BufferedInputStream. Hier is code die beide opties demonstreert:

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())); 
   }
}
Bij het lezen van een bestand van 1,5 MB op mijn computer FileInputStreamvoltooide ik het werk in ~ 3500 milliseconden, maar BufferedInputStreamslaagde het in ~ 1700 milliseconden. Zoals je kunt zien, optimaliseerde de gebufferde stream het werk en halveerde het! :) We zullen doorgaan met het bestuderen van I/O-klassen - tot ziens!
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION