- Classificação de Streams
O pacote java.io fornece classes para manipulação de entrada e saída.
1.1 Streams de Entrada e Saída
A classe File não pode acessar o conteúdo do arquivo diretamente. Para isso, utiliza-se streams de entrada/saída. A direção é sempre relativa à memória: dados que entram na memória vêm de uma stream de entrada, e dados que saem da memória vão para uma stream de saída.
1.2 Streams de Bytes e Caracteres
Existem duas categorias principais:
- Streams de bytes:
InputStream,OutputStream - Streams de caracteres:
Reader,Writer,BufferedReader
1.3 Streams de Nó e Streams de Processamento
Streams de processamento permitem adicionar funcionalidades aos streams de nó:
Exemplo de Streams de Processamento
FileOutputStream fos = new FileOutputStream("dados.txt");
PrintStream ps = new PrintStream(fos);
ps.println("Primeira linha de texto");
ps.println("Segunda linha de texto");
ps.close();
fos.close();
- Streams de Conversão
Apenas conversión entre streams de bytes e caracteres. Utiliza-se InputStreamReader e OutputStreamWriter.
InputStreamReader leitor = new InputStreamReader(System.in);
BufferedReader buffer = new BufferedReader(leitor);
String linha = buffer.readLine();
System.out.println("Digitado: " + linha);
buffer.close();
- Stream de Pushback
Permite retornar caracteres ao buffer de entrada.
- Redirecionamento de Entrada/Saída Padrão
System.setErr(PrintStream erro);
System.setIn(InputStream entrada);
System.setOut(PrintStream saida);
- Leitura e Escrita de Dados de Outros Processos
InputStream fluxoErro = processo.getErrorStream();
InputStream fluxoEntrada = processo.getInputStream();
OutputStream fluxoSaida = processo.getOutputStream();
Exemplo de Execução de Processo
Process processo = Runtime.getRuntime().exec("java -version");
BufferedReader leitor = new BufferedReader(
new InputStreamReader(processo.getErrorStream()));
String conteudo = null;
while ((conteudo = leitor.readLine()) != null) {
System.out.println(conteudo);
}
leitor.close();
Utilização do Scanner
Scanner sc = new Scanner(System.in);
String entrada = sc.nextLine();
- RandomAccessFile
Esta classe permite leitura e escrita direta em arquivos. É possível mover o ponteiro para qualquer posição. Atenção: ao inserir dados no meio do arquivo, o conteúdo a partir da posição do ponteiro será sobrescrito.
Métodos para操作指针:
long getFilePointer(): retorna a posição atual do ponteirovoid seek(long pos): move o ponteiro para uma posição específica
Métodos de Leitura/Escrita:
read()write()
Exemplo de Uso
RandomAccessFile arquivo = new RandomAccessFile("documento.txt", "r");
arquivo.seek(100);
int byteLido = arquivo.read();
System.out.println("Byte na posição 100: " + byteLido);
arquivo.close();
- Serialização de Objetos
Uma classe deve implementar Serializable ou Externalizable para ser serializável. Geralmente, cada JavaBean implementa Serializable.
7.1 Utilizando Streams de Objetos
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("objeto.dat"));
Pessoa pessoa = new Pessoa("Maria", 25);
oos.writeObject(pessoa);
oos.close();
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("objeto.dat"));
Pessoa p = (Pessoa) ois.readObject();
System.out.println("Nome: " + p.getNome());
ois.close();
Observação importante: A desserialização lê dados do objeto, não da classe. Portanto, o arquivo .class deve estar disponível. O mecanismo de desserialização não utiliza construtores.
Quando um objeto é serializado múltiplas vezes, apenas a primeira serialização gera a sequência de bytes completa. As subsequentes apenas gravam uma referência ao identificador já existente. Além disso, alterações feitas no objeto após a primeira serialização não são incluídas em serializações posteriores.
7.2 Serialização Personalizada
Para excluir um campo da serialização:
private transient int idade;
Para personalização avançada: antes da serialização, o método writeReplace() é chamado, seguido de writeObject(). Na desserialização, readObject() é executado primeiro, e depois readResolve(), cujo retorno substitui o resultado anterior. Isso é útil para classes singleton e enumerações.
Itens serializados: nome da classe, variáveis de instância (incluindo tipos primitivos, arrays e referências a outros objetos). Não são serializados: métodos, variáveis de classe e variáveis de instância transient.
7.3 Implementando Externalizable
A interface Externalizable permite controlar complteamente o processo de serialização.
- NIO (New Input/Output)
8.1 Buffer
Representa um container de dados com capacidade limitada. Tipos disponíveis:
CharBufferByteBufferShortBufferIntBufferLongBufferFloatBufferDoubleBuffer
CharBuffer e ByteBuffer são os mais utilizados.
Relação entre índices: 0 ≤ mark ≤ position ≤ limit ≤ capacity
Métodos Principais
allocate(int capacidade): cria um bufferflip(): alterna para modo de leituraclear(): limpa o buffer para reuse
Exemplo de Uso
CharBuffer buffer = CharBuffer.allocate(10);
System.out.println("Capacidade: " + buffer.capacity());
System.out.println("Limite: " + buffer.limit());
System.out.println("Posição: " + buffer.position());
System.out.println("\nInserindo dados:");
buffer.put('X');
System.out.println("Posição = " + buffer.position());
buffer.put('Y');
System.out.println("Posição = " + buffer.position());
buffer.put('Z');
System.out.println("Posição = " + buffer.position());
System.out.println("\nAlterando para modo de leitura:");
buffer.flip();
System.out.println("Limite = " + buffer.limit());
System.out.println("Posição = " + buffer.position());
System.out.println("\nLendo dados:");
System.out.println(buffer.get());
System.out.println("Posição = " + buffer.position());
System.out.println(buffer.get());
System.out.println("Posição = " + buffer.position());
System.out.println(buffer.get());
System.out.println("Posição = " + buffer.position());
System.out.println("\nLimpando buffer:");
buffer.clear();
System.out.println("Limite = " + buffer.limit());
System.out.println("Posição = " + buffer.position());
8.2 Channel
Um canal representa uma conexão aberta com um dispositivo de E/S, como um arquivo ou soquete. O programa não pode acessar diretamente os dados do canal; deve interagir através de um buffer.
Tipos de Channel
FileChannelDatagramChannelPipe.SinkChannelPipe.SourceChannel
Todos os canais são obtidos através do método getChannel() das classes de streams de nó.
Métodos do Channel
map(): mapeia uma região do arquivo em memóriaread(): lê dados para o bufferwrite(): escreve dados do buffer
8.3 Charset
Utilizado para converter entre sequências de bytes e caracteres.
import java.nio.charset.*;
import java.nio.*;
public class TesteCharset {
public static void main(String[] args) throws CharacterCodingException {
Charset utf8 = Charset.forName("UTF-8");
CharsetEncoder codificador = utf8.newEncoder();
CharsetDecoder decodificador = utf8.newDecoder();
CharBuffer texto = CharBuffer.allocate(10);
texto.put('B');
texto.put('r');
texto.put('a');
texto.put('s');
texto.put('i');
texto.put('l');
texto.flip();
ByteBuffer bytes = codificador.encode(texto);
for (int i = 0; i < bytes.capacity(); i++) {
System.out.println(bytes.get(i));
}
System.out.println("\nTexto decodificado: " + decodificador.decode(bytes));
}
}
8.4 Bloqueio de Arquivos
O NIO permite bloquear seções de um arquivo para acesso exclusivo:
lock(): bloqueia permanentemente até releasetryLock(): tenta bloquear, retorna null se não conseguir