Olá! A palestra de hoje será dividida em duas partes. Repetiremos alguns dos tópicos antigos que já abordamos antes e veremos alguns novos recursos :) Vamos começar com o primeiro. A repetição é a mãe do aprendizado :) Você já usou uma aula como
BufferedReader
. Espero que você ainda não tenha esquecido este comando:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Antes de continuar lendo, tente lembrar pelo que cada componente ( System.in, InputStreamReader, BufferedReader
) é responsável e para que são necessários. Ocorrido? Se não, não se preocupe :) Se a essa altura você já esqueceu alguma coisa, releia esta palestra dedicada aos leitores. Vamos lembrar brevemente o que cada um deles pode fazer. System.in
é um thread para receber dados do teclado. Em princípio, para implementar a lógica de leitura do texto, bastaria um para nós. Mas, como você lembra, System.in
ele só pode ler bytes, não caracteres:
public class Main {
public static void main(String[] args) throws IOException {
while (true) {
int x = System.in.read();
System.out.println(x);
}
}
}
Se executarmos este código e inserirmos a letra “Y” no console, a saída será assim:
Й
208
153
10
Os caracteres cirílicos ocupam 2 bytes na memória, que são exibidos na tela (e o número 10 é a representação de bytes de uma quebra de linha, ou seja, pressionando Enter). Ler bytes é um prazer, então usá-lo System.in
em sua forma pura será inconveniente. Para ler letras cirílicas (e não apenas) que sejam compreensíveis para todos, usamos InputStreamReader
como invólucro:
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);
}
}
}
Se inserirmos a mesma letra “Y” no console, o resultado desta vez será diferente:
Й
1049
10
InputStreamReader
converteu os dois bytes lidos (208, 153) em um único número 1049. Isso é leitura por caracteres. 1049 corresponde à letra “Y”, que pode ser facilmente verificada:
public class Main {
public static void main(String[] args) throws IOException {
char x = 1049;
System.out.println(x);
}
}
Saída do console:
Й
Bem, quanto a BufferedReader
'a (e em geral - BufferedAnything), classes em buffer são usadas para otimizar o desempenho. Acessar uma fonte de dados (arquivo, console, recurso na Internet) é uma operação bastante cara em termos de desempenho. Portanto, para reduzir o número dessas chamadas, BufferedReader
ele lê e acumula dados em um buffer especial, de onde posteriormente podemos recebê-los. Como resultado, o número de chamadas para a fonte de dados é reduzido várias vezes ou até dezenas de vezes! Outro recurso adicional de BufferedReader
'a e sua vantagem sobre o regular InputStreamReader
' é o método extremamente útil readLine()
que lê dados como strings inteiras em vez de números individuais. É claro que isso aumenta muito a conveniência ao implementar, por exemplo, texto grande. Esta é a aparência da leitura de uma linha:
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("Пользователь ввел следующий текст:");
System.out.println(s);
reader.close();
}
}
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Пользователь ввел следующий текст:
BufferedReader+InputStreamReader работает быстрее, чем просто InputStreamReader
Claro, BufferedReader
é um mecanismo muito flexível e permite trabalhar não apenas com o teclado. Você pode ler dados, por exemplo, diretamente da Internet, simplesmente passando a URL necessária ao leitor:
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();
}
}
Você pode ler dados de um arquivo passando o caminho para ele:
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();
}
}
Substituição de System.out
Agora vamos examinar uma possibilidade interessante que não abordamos antes. Como você provavelmente se lembra,System
existem dois campos estáticos na classe - System.in
e System.out
. Esses irmãos gêmeos são objetos da classe thread. System.in
- classe abstrata InputStream
. Uma System.out
aula PrintStream
. Agora falaremos especificamente sobre System.out
. Se entrarmos no código fonte da classe System
, veremos o seguinte:
public final class System {
……………...
public final static PrintStream out = null;
…………
}
Então, System.out
apenas uma variável de classe estática regularSystem
. Não há mágica nisso :) A variável out
pertence à classe PrintStream
. Aqui está uma pergunta interessante: por que, ao executar o código, System.out.println()
a saída aparece no console e não em outro lugar? E é possível mudar isso de alguma forma? Por exemplo, queremos ler dados do console e gravá-los em um arquivo de texto. É possível implementar de alguma forma essa lógica sem usar classes adicionais de leitor e gravador, mas simplesmente usando System.out
? Ainda quanto possível :) E embora a variável System.out
seja designada por um modificador final
, ainda podemos fazê-lo! Então, o que precisamos para isso? Primeiramente , precisamos de um novo objeto de classe PrintStream
em vez do atual. O objeto atual instalado na classe System
por padrão não nos convém: ele aponta para o console. Precisamos criar um novo que aponte para um arquivo de texto como “destino” de nossos dados. Em segundo lugar , você precisa entender como atribuir um novo valor a uma variável System.out
. Você não pode simplesmente fazer assim, porque está marcado final
. Vamos começar do fim. A classe System
contém exatamente o método que precisamos - setOut()
. Ele pega um objeto como entrada PrintStream
e o define como ponto de saída. Exatamente o que precisamos! Resta apenas criar o objeto PrintStream
. Isso também é fácil de fazer:
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
Todo o código ficará assim:
public class SystemRedirectService {
public static void main(String arr[]) throws FileNotFoundException
{
PrintStream filePrintStream = new PrintStream(new File("C:\\Users\\Username\\Desktop\\test.txt"));
/*Сохраним текущее meaning System.out в отдельную переменную, чтобы потом
можно было переключиться обратно на вывод в консоль*/
PrintStream console = System.out;
// Присваиваем System.out новое meaning
System.setOut(filePrintStream);
System.out.println("Эта строка будет записана в текстовый файл");
// Возвращаем System.out старое meaning
System.setOut(console);
System.out.println("А эта строка - в консоль!");
}
}
Como resultado, a primeira linha será gravada em um arquivo de texto e a segunda será enviada para o console :) Você pode copiar este código para o seu IDE e executá-lo. Ao abrir o arquivo de texto, você verá que a linha necessária foi escrita com sucesso :) Isso conclui a palestra. Hoje lembramos de como trabalhar com streams e leitores, lembramos como eles diferem entre si e aprendemos sobre novos recursos System.out
que usamos em quase todas as aulas :) Até as próximas palestras!
GO TO FULL VERSION