Java

Input/Output em Java

A entrada e saída (Input/Output) em Java é um conceito essencial ao se trabalhar com Java. Ele consiste em elementos como entrada, saída e fluxo.

A entrada são os dados que damos ao programa. A saída são os dados que recebemos do programa na forma de resultado.

Stream representa o fluxo de dados ou a sequência de dados. Para dar entrada, usamos o fluxo de entrada e para dar saída, usamos o fluxo de saída.

Com o Java, a tarefa de leitura e gravação de arquivos é facilitada em comparação com outras linguagens de programação.

Por ser uma linguagem orientada a objetos, é aconselhável a utilização de classes e objetos para manipular a entrada e saída de dados (INPUT/OUTPUT).

A linguagem Java trata a entrada e saída como fluxos de dados (streams).

java.io.File

Instâncias da classe java.io.File representam caminhos (paths) para possíveis locais no sistema operacional. Lembre-se que ele apenas representa um arquivo ou diretório.

Por exemplo, o código a seguir cria uma instância da classe mencionada, que aponta para /usr/guj/arquivo.txt:

File file = new File("/usr/guj/arquivo.txt"); 

E o código a seguir um caminho para o arquivo arquivo.txt que estará no diretório atual do sistema e ../arquivo.txt que estará no diretório pai do atual.

No caso do sistema operacional windows, você deve usar duplas barras invertidas (\\), já que uma barra invertida apenas é considerado escape pelo java.

Em java, você não tem como alterar o diretório atual, por isso pode criar instâncias da classe File que apontam para lugares relativos, mas sempre ao diretório inicial, veja o exemplo abaixo:

File noDiretorioAtual = new File("arquivo.txt");  
File noDiretorioAnterior = new File("../arquivo.txt");

Existe outras maneiras de criar caminhos relativos a um outro caminho, por exemplo:

File diretorioRaiz = new File("/");  
File arquivo1 = new File(diretorioRaiz,"autoexec.bat");  
File arquivo2 = new File(diretorioRaiz,"config.sys"); 
File diretorioWindows = new File(diretorioRaiz,"windows");  
File diretorioWindows2 = new File("/windows/"); 
File diretorioWindows3 = new File("/windows");  
File diretorioWindows4 = new File("c:\\windows");

É importante saber que criar um ponteiro para um caminho no sistema operacional não significa criar o arquivo/diretório.

As instanciações do código acima iriam funcionar mesmo se você não possuisse esses arquivos, porém não irão apontar para um arquivo/diretório existente.

Um pouco mais da API da classe java.io.File

Vamos mostrar um pouco mais da API desta classe, para que você saiba o que tem disponível. O primeiro passo é descobrir se uma instância da classe java.io.File aponta para algo que existe, para um diretório ou arquivo. Os três métodos úteis nesse momento são:

boolean exists(); 
boolean isDirectory();  
boolean isFile();

Outros métodos que podem ser úteis para checar a viabilidade de leitura e gravaçã sao:

boolean canRead(); 
boolean canWrite(); 

E por fim, alguns métodos de criação de diretórios, sendo o primeiro o que cria um diretório e o segundo cria todos os diretórios necessarios para chegar no caminho apontado pelo objeto. Esses costumam ser muito utilizados:

boolean mkdir();  
boolean mkdirs();

E outros métodos comuns são:

boolean mkdir();  
boolean mkdirs();

O Java tem duas camadas de IO. Um baixo, que lê e escreve bytes, e um alto, que escreve e le caracteres.

Vamos ver os de alto nível, juntamente com algum encapsulando por cima deste, pois o de alto nível mexe com chars, e o que encapsula mexe com tudo.

O rescritor de caracteres que iremos usar será uma instância da classe java.io.FileWriter:

FileWriter writer = new FileWriter(new File("saida.txt"),true);  
FileWriter writer = new FileWriter(new File("saida.txt"));  
FileWriter writer = new FileWriter("saida.txt",true); 
FileWriter writer = new FileWriter("saida.txt"); 

As duas primeiras linhas obtém o mesmo resultado que a terceira e a quarta, pois existem construtores para objetos do tipo File e String.

Se você especificar um segundo parâmetro como true (primeira e terceira linha), você pode dizer que deseja adicionar dados a um arquivo que ja existe em vez de sobregravar esse arquivo (modo append).

Agora já temos uma instância do “gravador” de caracteres, mas desejamos escrever Strings para o arquivo utilizando uma instância da classe java.io.PrintWriter que fornece as funcoes print() e println(0).

PrintWriter saida = new PrintWriter(writer); 
PrintWriter saida = new PrintWriter(writer,true);

Especificando o segundo parâmetro como true, os dados serão enviados para o arquivo a toda chamada do método println(), caso contrário, os dados só são enviados quando você enviar uma quebra de linha, fechar o arquivo ou mandar ele atualizar as mudanças (modo autoflush).

Repare que você utiliza um objeto da classe java.io.PrintWriter, o System.out é uma instância desta classe, obviamente encapsulando uma outra Stream. Agora você já pode escrever no arquivo que abriu:

saida.println("Tenho dinheiro,");  
saida.println("saúde, ");  
saida.println("e muita paz!");

Agora você deve fechar o arquivo na ordem contrária que abriu, por segurança:

saida.close(); 
writer.close(); 

Sempre feche esses objetos, que liberam recursos para o sistema. Não confie no Garbage Collector!

java.io.FileReader e java.io.BufferedReader

Assim como sobre a escrita, você deve conhecer o API das classes java.io.FileInputStream e java.io.InputStreamWriter para utilizar de métodos compatíveis com caracteres UNICODE.

O leito de caracteres que iremos usar durante a leiturá sera uma instância da classe java.io.FileReader:

FileReader reader = new FileReader(new File("saida.txt"));  
FileReader reader = new FileReader("saida.txt");  

Como no exemplo de escrita, as duas linhas acima possuem o mesmo resultado.

Agora, instanciamos um objeto da classe java.io.BufferedReader que fornece a funcao readLine() e algumas outras, para agilizar o trabalho.

BufferedReader leitor = new BufferedReader(reader); 
BufferedReader leitor = new BufferedReader(reader,1*1024*1024);

Você pode especificar o tamanho do buffer desejado no segundo parâmetro.

Esse buffer é utilizado para minimizar o número de pedidos de io para ler blocos maiores do arquivo de uma vez só. Aumentando esse número diminui os acessos a disco, mas aumenta o consumo de memória! Agora você já pode ler:

String linha = null;  
    
while((linha = leitor.readLine())) {
	
   System.out.println("Linha: " + linha); 
}

Não se esqueça de fechar os dois objetos:

leitor.close();  
reader.close();

java.io.BufferedWriter

Você pode utilizar a classe BufferedWriter para agilizar também o processo de gravação:

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("saida.txt"))); 
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("saida.txt"),
1*1024*1024)); 

Caso você não utilize um objeto BufferedWriter no meio, voce terá como resultado uma conversão de caracteres em bytes e gravação no arquivo a cada chamada do método print e suas variantes, o que pode ser muito custoso. 

DOMINE O JAVA WEB ATRAVÉS DE AULAS PASSO A PASSO, DO BÁSICO AO AVANÇADO!

Domine as boas práticas com projetos práticos que vão te ajudar a desenvolver sistemas e se destacar no mercado de programação.

Clique na imagem abaixo e conheça mais detalhes do nosso curso:

Link do curso: https://go.hotmart.com/S90628636G?src=siteCB

Recursividade em Java

Dúvidas ou sugestões? Deixem nos comentários! Para mais dicas, acesse o nosso canal no YouTube:
https://youtube.com/criandobits

Bene Silva Júnior

Bacharel em Sistemas de Informação pelo Instituto Paulista de Pesquisa e Ensino IPEP. Apaixonado por tecnologias e games do tempo da vovó!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *