CIAO! La lezione di oggi sarà divisa in due parti per comodità. Ripeteremo alcuni vecchi argomenti che abbiamo toccato in precedenza e prenderemo in considerazione alcune nuove funzionalità :) Iniziamo con il primo. Hai già una classe come
BufferedReader
molte volte. Spero che tu non abbia avuto il tempo di dimenticare questa affermazione:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Prima di continuare a leggere, cerca di ricordare di cosa è responsabile ciascun componente — System.in
, InputStreamReader
, BufferedReader
— e perché è necessario. Ricordavi? In caso contrario, non preoccuparti. :) Se hai dimenticato qualcosa, rileggi questa lezione , che è dedicata alle lezioni di lettura. Ricorderemo brevemente cosa può fare ognuno di loro. System.in
— questo è un flusso per ricevere dati dalla tastiera. In linea di principio, basterebbe da solo per implementare la logica richiesta per leggere il testo. Ma, come ricorderete, System.in
può leggere solo byte, non caratteri:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
Se eseguiamo questo codice e inseriamo la lettera cirillica "E", l'output sarà:
Й
208
153
10
I caratteri cirillici occupano 2 byte in memoria e vengono visualizzati sullo schermo. Il numero 10 è la rappresentazione decimale di un carattere di avanzamento riga, ovvero dalla pressione di Invio. Leggere i byte è un tale piacere, quindi l'utilizzo System.in
non è molto conveniente. Per leggere correttamente le lettere cirilliche (e altre), usiamo InputStreamReader
come wrapper:
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);
}
}
}
Inseriamo la stessa lettera "Й", ma questa volta il risultato è diverso:
Й
1049
10
InputStreamReader
ha convertito due byte (208 e 153) nell'unico numero 1049. Questo è ciò che significa leggere i caratteri. 1049 corrisponde alla lettera cirillica "Й". Possiamo facilmente convincerci che questo è vero:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
Uscita console:
Й
E come forBufferedReader
(e in generale, BufferedAnythingYouWant
), le classi bufferizzate vengono utilizzate per ottimizzare le prestazioni. L'accesso a un'origine dati (file, console, risorsa Web) è piuttosto costoso in termini di prestazioni. Pertanto, al fine di ridurre il numero di accessi, BufferedReader
legge e accumula i dati in un apposito buffer, e da lì li otteniamo. Di conseguenza, il numero di accessi all'origine dati viene ridotto, probabilmente di diversi ordini di grandezza! Un'altra delle BufferedReader
caratteristiche di , e il suo vantaggio rispetto all'ordinario , è il metodo InputStreamReader
estremamente utile , che legge intere righe di dati, non singoli numeri. readLine()
Questo, ovviamente, è super conveniente quando si ha a che fare con testi di grandi dimensioni. Ecco come appaiono le righe di lettura:
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
Certo, BufferedReader
è molto flessibile. Non sei limitato a lavorare con la tastiera. Ad esempio, puoi leggere i dati direttamente dal Web, semplicemente passando l'URL richiesto a un lettore:
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();
}
}
Puoi leggere i dati da un file passando il percorso del file:
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();
}
}
Sostituzione di System.out
Ora diamo un'occhiata a una capacità interessante che non abbiamo toccato prima. Come sicuramente ricorderete, laSystem
classe ha due campi statici — System.in
e System.out
. Questi fratelli gemelli sono oggetti di flusso. System.in
è un InputStream
. Ed System.out
è un PrintStream
. In questo momento, parleremo di System.out
. Se entriamo nel System
codice sorgente della classe, vediamo questo:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
Pertanto, System.out
è semplicemente una normale variabile statica dellaSystem
classe. Non c'è niente di magico in questo :) La out
variabile è un PrintStream
riferimento. Ecco una domanda interessante: quando System.out.println()
viene eseguito, perché esattamente l'output va alla console e non da qualche altra parte? E questo può essere cambiato in qualche modo? Ad esempio, supponiamo di voler leggere i dati dalla console e scriverli in un file di testo. È possibile in qualche modo implementarlo semplicemente usando System.out
piuttosto che classi di lettura e scrittura aggiuntive? In effetti lo è :) E possiamo farlo anche se la System.out
variabile è contrassegnata con il final
modificatore! Quindi di cosa abbiamo bisogno per farlo accadere? Prima di tutto, abbiamo bisogno di un nuovo PrintStream
oggetto per sostituire quello attuale. L'oggetto corrente, impostato nel fileSystem
class per impostazione predefinita, non serve ai nostri scopi: punta alla console. Devi crearne uno nuovo che punti a un file di testo, la "destinazione" per i nostri dati. In secondo luogo, dobbiamo capire come assegnare un nuovo valore alla System.out
variabile. Non è possibile utilizzare un semplice operatore di assegnazione perché la variabile è contrassegnata con final
. Lavoriamo a ritroso dalla fine. Si dà il caso che la System
classe abbia il metodo di cui abbiamo bisogno: setOut()
. Prende un PrintStream
oggetto e lo imposta come destinazione per l'output. È proprio quello di cui abbiamo bisogno! Non resta che creare un PrintStream
oggetto. Anche questo è facile:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
Il codice completo sarà simile a questo:
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!");
}
}
Di conseguenza, la prima stringa viene scritta nel file di testo e la seconda viene visualizzata nella console :) Puoi copiare questo codice nel tuo IDE ed eseguirlo. Apri il file di testo e vedrai che la stringa è stata scritta con successo lì :) Con questo, la nostra lezione è giunta al termine. Oggi abbiamo ricordato come lavorare con stream e lettori. Abbiamo ricordato come differiscono l'uno dall'altro e abbiamo appreso alcune nuove funzionalità di System.out
, che abbiamo utilizzato in quasi tutte le lezioni :) Fino alle prossime lezioni!
Altre letture: |
---|
GO TO FULL VERSION