"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
:) 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
Hier hoe het eruit ziet om gegevens uit een bestand te lezen met behulp van

BufferedReader
, evenals de InputStream
en OutputStream
abstracte klassen en verschillende afstammelingen Vandaag zullen we 3 nieuwe klassen bekijken: FileInputStream
, FileOutputStream
, en BufferedInputStream
.
De FileOutputStream-klasse
Het belangrijkste doel van deFileOutputStream
klasse is om bytes naar een bestand te schrijven. Niets ingewikkelds :) FileOutputStream
is een van de implementaties van de OutputStream
abstracte klasse. In de constructor nemen objecten van deze klasse het pad naar het doelbestand (waar de bytes moeten worden geschreven) of een File
object. 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 File
object 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, FileOutputStream
kan 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
HetFileInputStream
heeft het tegenovergestelde doel: het lezen van bytes uit een bestand. Net zoals FileOutputStream
erft OutputStream
, is deze klasse afgeleid van de InputStream
abstracte 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"

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 deBufferedInputStream
klas 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 BufferedInputStream
leest 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 BufferedInputStream
object gemaakt. De constructor neemt een instantie van de InputStream
klasse of een van zijn afstammelingen, dus dat FileInputStream
zal 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 FileInputStream
en 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 FileInputStream
voltooide ik het werk in ~ 3500 milliseconden, maar BufferedInputStream
slaagde 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!
GO TO FULL VERSION