Hoi! De les van vandaag zal voor het gemak in twee delen worden verdeeld. We zullen enkele oude onderwerpen herhalen die we eerder hebben besproken, en we zullen enkele nieuwe functies overwegen :) Laten we beginnen met de eerste.
BufferedReader
Je hebt al zo vaak een klas gehad . Ik hoop dat je geen tijd hebt gehad om deze verklaring te vergeten:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Probeer voordat u verder leest te onthouden waar elk onderdeel - System.in
, InputStreamReader
, BufferedReader
- verantwoordelijk voor is en waarom het nodig is. Weet je het nog? Zo niet, geen zorgen. :) Als je iets bent vergeten, herlees dan deze les , die is gewijd aan lezersklassen. We zullen kort herinneren aan wat elk van hen kan doen. System.in
— dit is een stroom voor het ontvangen van gegevens van het toetsenbord. In principe zou het alleen voldoende zijn om de logica te implementeren die nodig is om tekst te lezen. Maar, zoals u zich zult herinneren, System.in
kan alleen bytes lezen, geen tekens:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
Als we deze code uitvoeren en de Cyrillische letter "Й" invoeren, is de uitvoer:
Й
208
153
10
Cyrillische tekens nemen 2 bytes in het geheugen in beslag en worden op het scherm weergegeven. Het getal 10 is de decimale weergave van een regelinvoerteken, dwz door op Enter te drukken. Het lezen van bytes is zo leuk, dus het gebruik System.in
is niet erg handig. Om Cyrillische (en andere) letters correct te lezen, gebruiken we InputStreamReader
als omhulsel:
public class Main {
public static void main(String[] args) throws IOException {
InputStreamReader reader = new InputStreamReader(System.in);
while (true) {
int x = reader.read();
System.out.println(x);
}
}
}
We voeren dezelfde letter "Й" in, maar het resultaat is deze keer anders:
Й
1049
10
InputStreamReader
converteerde twee bytes (208 en 153) naar het enkele getal 1049. Dit is wat het betekent om karakters te lezen. 1049 komt overeen met de Cyrillische letter "Й". We kunnen onszelf gemakkelijk overtuigen dat dit waar is:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
Console-uitvoer:
Й
En aangezien forBufferedReader
(en in het algemeen BufferedAnythingYouWant
) gebufferde klassen worden gebruikt om de prestaties te optimaliseren. Toegang tot een gegevensbron (bestand, console, webresource) is vrij duur in termen van prestaties. Daarom, om het aantal toegangen te verminderen, BufferedReader
leest en verzamelt het gegevens in een speciale buffer, en we halen het vanaf daar. Als gevolg hiervan wordt het aantal keren dat de gegevensbron wordt geopend, verlaagd - mogelijk met meerdere ordes van grootte! Een ander BufferedReader
kenmerk en het voordeel ervan ten opzichte van de gewone InputStreamReader
, is de uiterst behulpzame readLine()
methode, die hele regels met gegevens leest, geen individuele nummers. Dit is natuurlijk superhandig als het om grote teksten gaat. Zo zien leesregels eruit:
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
System.out.println ("The user entered the following text:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader is faster than InputStreamReader alone
The user entered the following text:
BufferedReader+InputStreamReader is faster than InputStreamReader alone
Is natuurlijk BufferedReader
heel flexibel. U bent niet beperkt tot het werken met het toetsenbord. U kunt bijvoorbeeld gegevens rechtstreeks van internet lezen door simpelweg de vereiste URL aan een lezer door te geven:
public class URLReader {
public static void main(String[] args) throws Exception {
URL oracle = new URL("https://www.oracle.com/index.html");
BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
U kunt gegevens uit een bestand lezen door het bestandspad door te geven:
public class Main {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("testFile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));
String str;
while ((str = reader.readLine()) != null) {
System.out.println (str);
}
reader.close();
}
}
System.out vervangen
Laten we nu eens kijken naar een interessante mogelijkheid die we nog niet eerder hebben besproken. Zoals je je zeker herinnert,System
heeft de klasse twee statische velden - System.in
en System.out
. Deze tweelingbroers zijn stroomobjecten. System.in
is een InputStream
. En System.out
is een PrintStream
. Op dit moment zullen we het hebben over System.out
. Als we in de System
broncode van de klasse vallen, zien we dit:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
Het is dus System.out
gewoon een gewone statische variabele van deSystem
klasse. Er is niets magisch aan :) De out
variabele is een PrintStream
referentie. Hier is een interessante vraag: wanneer System.out.println()
wordt uitgevoerd, waarom gaat de uitvoer precies naar de console en niet ergens anders? En kan dit op de een of andere manier veranderd worden? Stel dat we gegevens van de console willen lezen en naar een tekstbestand willen schrijven. Is het mogelijk om dit op de een of andere manier eenvoudig te implementeren door gebruik te maken van System.out
in plaats van extra lezers- en schrijversklassen? Inderdaad, dat is het :) En we kunnen het doen, ook al System.out
is de variabele gemarkeerd met de final
modifier! Dus wat hebben we nodig om dit voor elkaar te krijgen? Allereerst hebben we een nieuw PrintStream
object nodig om het huidige te vervangen. Het huidige object, ingesteld in deSystem
class, dient niet onze doeleinden: het verwijst naar de console. U moet een nieuwe maken die verwijst naar een tekstbestand - de "bestemming" voor onze gegevens. Ten tweede moeten we begrijpen hoe we een nieuwe waarde aan de System.out
variabele kunnen toekennen. U kunt geen eenvoudige toewijzingsoperator gebruiken, omdat de variabele is gemarkeerd met final
. Laten we vanaf het einde achteruit werken. Toevallig System
heeft de klasse de methode die we nodig hebben: setOut()
. Het neemt een PrintStream
object en stelt het in als de bestemming voor uitvoer. Dat is precies wat we nodig hebben! Het enige dat overblijft is het creëren van een PrintStream
object. Dit is ook makkelijk:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
De volledige code ziet er als volgt uit:
public class SystemRedirectService {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
/* Save the current value of System.out in a separate variable so that later
we can switch back to console output */
PrintStream console = System.out;
// Assign a new value to System.out
System.setOut(filePrintStream);
System.out.println("This line will be written to the text file");
// Restore the old value of System.out
System.setOut(console);
System.out.println("But this line will be output to the console!");
}
}
Het resultaat is dat de eerste string naar het tekstbestand wordt geschreven en de tweede wordt weergegeven in de console :) U kunt deze code naar uw IDE kopiëren en uitvoeren. Open het tekstbestand en je zult zien dat de string daar met succes is geschreven :) Hiermee is onze les tot een einde gekomen. Vandaag herinnerden we ons hoe we met streams en lezers kunnen werken. We herinnerden ons hoe ze van elkaar verschillen en leerden over enkele nieuwe mogelijkheden van System.out
, die we in bijna elke les hebben gebruikt :) Tot de volgende lessen!
Meer lezen: |
---|
GO TO FULL VERSION