E/S básica no terminal e uso da classe System

Computação II - Ciência da Computação


Prof.: Danilo S. Carvalho

Nessa aula, vamos conhecer os mecanismos básicos de entrada e saída no terminal em Java.


Ao final da aula, poderemos processar dados obtidos através de entrada do usuário e colocar saída formatada no terminal (standard I/O).

Assim como a linguagem C, o Java oferece ao programador meios simples de acessar a entrada e saída padrão do sistema (standard I/O).

Isso é feito através da classe System, parte da biblioteca padrão do Java.

Conforme aprendemos na aula sobre pacotes, todas as classes do Java devem ser organizadas em uma hierarquia de pacotes.

Isso não é diferente para as classes da biblioteca padrão, que acompanham a JDK. Elas estão contidas no pacote java e seus subpacotes.

Por exemplo, a classe String é parte do pacote java.lang. Esse pacote é o único que é importado automaticamente.

Dessa forma, não precisamos escrever "import java.lang.String;" no início de todos os arquivos que usam a classe String.

Nem escrever java.lang.String toda vez que declaramos uma variável do tipo String.

O mesmo se aplica às classes System, Math (operações matemáticas), entre outras.

A classe System contem métodos e campos (ou atributos) para acessar funções importantes da máquina virtual, inclusive as entradas e saídas.

Há três campos dedicados a tal fim: in, out e err.

out e err são campos do tipo PrintStream, que permitem enviar dados para a saída padrão e para a saída de erro, respectivamente. Equivalente aos ponteiros stdout e stderr em C.

in é um campo do tipo InputStream, que permite ler da entrada padrão. Equivalente ao ponteiro stdin em C.

Para escrever na saída padrão, usamos os métodos print* do campo out (ver API da classe PrintStream). Por exemplo, o método println​(String x)

Há também o método printf​(String format, Object... args), que é usado de maneira quase idêntica ao C.

O mesmo se aplica ao System.err.

                        
                            System.out.println("Imprime essa string na saída padrão e pula uma linha");
                        
                    
                        
                            int ano = 2020;
                            System.out.printf("O ano é %d", ano);
                        
                    

Para ler da entrada padrão, entretanto, não há um método prático oferecido em System.in.

System.in.read() permite apenas ler bytes, o que não nos ajuda muito.

Usaremos então a classe java.util.Scanner, que facilita a leitura dos dados.

Dentro de um método, criamos um novo Scanner. Isso é feito com a palavra chave new.

O new alocará a memória necessária para armazenar o novo Scanner, e resultará em uma referência, que será atribuída à variável. Similar ao malloc em C.

Além disso, toda classe possui pelo menos um método chamado "construtor", que possui o mesmo nome da classe.

Esse método é chamado toda vez que uma nova instância de uma classe é criada, que daqui em diante chamaremos de objeto.

Como exemplo, o literal "Olá mundo" é uma instância da classe String, e portanto um objeto.

O campo System.in é uma instância da classe InputStream, e portanto também é um objeto.

Um construtor da classe Scanner tem como argumento um objeto InputStream de onde serão lidos os dados.

Passamos o campo System.in, que é um InputStream representando a entrada padrão.

A classe Scanner possui um método chamado nextLine() (ver API) que lê uma linha (String) do seu InputStream.

Ao chamar o método nextLine(), o terminal ficará aguardando o usuário digitar algo e apertar a tecla Enter, terminando a linha.

A linha digitada então será armazenada na variável "linha".

Podemos agora imprimir a linha que lemos na saída padrão, acompanhada do tamanho dela, em caracteres, obtido usando o método length() da classe String.

                        
                            import java.util.Scanner;
                        
                    
                        
                            Scanner scanner = new Scanner(System.in);
                        
                    
                        
                            Scanner scanner = new Scanner(System.in);
                            String linha = scanner.nextLine();
                        
                    
                        
                            Scanner scanner = new Scanner(System.in);
                            String linha = scanner.nextLine(); 

                            System.out.printf("%s possui %d caracteres\n", linha, linha.length());
                            System.out.println("Fim!");
                        
                    

Agora podemos criar programas que lêem strings da entrada padrão e realizar operações sobre elas.


Consultem a documentação das classes PrintStream, Scanner e String, para descobrir maneiras de ler outros tipos: int, float...

Dica: para cada tipo primitivo do Java existe uma classe correspondente em java.lang, que nos permite converter strings no respectivo tipo (ex: string -> double).

Perguntas:

  1. Quando devemos usar o campo System.err?
  2. Posso imprimir um número float usando System.out.println, em vez de System.out.printf?
  3. Apesar do tipo de retorno do método main ser void, há um método da classe System que permite a máquina virtual Java retornar um código de erro. Que método é esse?

Até a próxima aula!