A função mais importante de um computador é processar dados. Uma linguagem de computador útil precisa ter bons recursos de IO para que os dados não processados fluam para o programa e os dados processados saiam.
Comparadas com outras linguagens, as funções IO do Java são complexas. Em outras linguagens, muitas funções IO (como leitura de arquivos) são encapsuladas e podem ser implementadas com uma ou duas linhas de programas. Em Java, os programadores geralmente precisam de vários níveis de decoração para conseguir ler arquivos.
O benefício da complexidade relativa é a flexibilidade do IO. Em Java, os programadores podem controlar todo o processo de IO para projetar o melhor método de IO. Veremos mais abaixo.
Exemplo de IO
Abaixo está o arquivo file.txt que usei para demonstração
Olá mundo! Olá Nerd!
Vamos primeiro estudar um exemplo de leitura de arquivo:
import java.io.*;public class Test{ public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader("file.txt")); while (linha! = nulo) { System.out.println(linha); linha = br.readLine(); e) { System.out.println("Problema de IO");
Este programa contém um manipulador de exceções try...catch...finally. Consulte o Tutorial Java Avançado sobre Tratamento de Exceções
Decoradores e combinações de funções
A chave para programar IO é criar um objeto BufferedReader br:
BufferedReader br = new BufferedReader(new FileReader("arquivo.txt"));
Durante o processo de criação, primeiro criamos um objeto FileReader. A função deste objeto é ler o fluxo de bytes do arquivo "file.txt" e convertê-lo em um fluxo de texto. Em Java, a codificação de texto padrão é unicode. BufferedReader() recebe o objeto FileReader, expande as funções de FileReader e cria um novo objeto BufferedReader. Além das funções de leitura e conversão de arquivos mencionadas acima, este objeto também fornece funções de leitura em cache (buffer). Finalmente, podemos ler o arquivo linha por linha chamando o método readLine() no objeto br.
(A leitura do cache serve para abrir uma área na memória como um cache, que armazena o fluxo de texto lido pelo FileReader. Quando o conteúdo do cache é lido (como o comando readLine()), o cache carregará o fluxo de texto subsequente.)
BufferedReader() é um decorador que recebe um objeto primitivo e retorna um objeto decorado com funções mais complexas. A vantagem dos decoradores é que eles podem ser usados para decorar diversos objetos. O que estamos modificando aqui é o fluxo de texto lido do arquivo. Outros fluxos de texto, como entrada padrão, fluxos de transmissão de rede, etc., podem ser modificados por BufferedReader() para obter leitura em cache.
O diagrama abaixo mostra como br funciona, com os dados fluindo de baixo para cima:
O processo de decoração acima é muito semelhante à ideia de fluxo de texto no Linux. No Linux, usamos uma abordagem semelhante a uma função para processar e passar fluxos de texto. Em Java, usamos decoradores. Mas seus objetivos são semelhantes, ou seja, alcançar a modularização e a livre combinação de funções.
mais combinações
Na verdade, Java oferece um rico conjunto de decoradores. FileReader combina as duas etapas de leitura e conversão e adota configurações padrão comumente usadas, como Unicode para codificação. Podemos utilizar a combinação de FileInputStream + InputStreamReader para substituir FileReader, separando assim as duas etapas de leitura de bytes e conversão, e tendo melhor controle sobre os dois processos.
(Claro, FileReader é mais conveniente de usar. InputStreamReader converte FileInputStream em um Reader para processar texto unicode)
As setas indicam a direção do fluxo de dados
A leitura e gravação de fluxo vêm de quatro classes básicas: InputStream, OutputStream, Reader e Writer. InputStream e Reader lidam com operações de leitura, e OutputStream e Writer lidam com operações de escrita. Ambos estão localizados no pacote java.io. A relação de herança é a seguinte:
java.io
Além disso, IOException possui as seguintes classes derivadas:
IOException
Reader e Writer e suas classes derivadas lidam com texto unicode. Como vemos Buffered Reader, InputStreamReader ou FileReader.
InputStream e OutputStream e suas classes derivadas lidam com fluxos de bytes. Os dados no computador podem ser considerados na forma de bytes, portanto InputStream e OutputStream podem ser usados para processar uma gama mais ampla de dados. Por exemplo, podemos usar a seguinte combinação para ler os dados (como números inteiros) contidos no arquivo compactado:
As setas indicam a direção do fluxo de dados
Lemos o fluxo de bytes do arquivo compactado, depois o descompactamos e, finalmente, lemos os dados.
escrever
As operações de gravação são semelhantes às operações de leitura. Podemos implementar funções de escrita complexas usando decorações. Aqui está um exemplo simples de escrita de texto:
import java.io.*;public class Test{ public static void main(String[] args) { try { String content = "Obrigado pelo seu peixe."; / cria o arquivo se não existir if (!file.exists()) { file.createNewFile() } FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.close();
O objeto de arquivo é criado acima para processar caminhos de arquivo.
Resumir
Esta é apenas uma introdução básica ao Java IO. O IO do Java é relativamente complexo. Os programadores Java precisam gastar algum tempo se familiarizando com as classes java.io e suas funcionalidades.