O Java NIO é uma das melhorias mais significantes para manipulação de I/O. A sigla NIO é de New I/O, ou seja, renovação do pacote java.io.* em relação ao acesso a recursos de memórias externas como um arquivo ou um cliente remoto (host). O pacote NIO está aninhado em java.nio.*.
Nota: I/O é o termo utilizado para denominar a troca de dados de uma área para outra em computação. Esta operação pode ser a comunicação ministrada por uma CPU para transitar dados da sua RAM para um HD, CD R/W, DVD R/W, pasta de rede, um PenDrive (flash), outro computador ou banco de dados. Numa linguagem de programação, este acesso é classificado de alto risco, pois quando os dados saem ou chegam de um recurso externo, muitas coisas podem ocorrer como o desligamento deste recurso, queda do meio físico da comunicação, falha no sistema lógico etc.
Durante minha experiência com Java NIO, me despertou atenção a sua capacidade de acesso não bloqueante. Isso mesmo, você escreve os dados em um recurso I/O como é um arquivo e pode programar para o gerenciador da escrita não deixar em espera sua linha de execução (thread). A mesma espera não é necessária se os dados enviados pelo recurso ainda não estiverem prontos.
O acesso não bloqueante torna possível a terceirização do controle de múltiplos I/O para o Java NIO sem requerer de você a criação de múltiplas threads (linhas de execução paralelas) para gerenciar este acesso. Entretanto, esta terceirização requer cuidados e domínio do tipo de recurso I/O referentes as cerimônias para abertura da comunicação, transferência de dados e encerramento da comunicação. O Java NIO não abstrai estes controles e caberá a você entender bem como funciona o tipo de recurso a operar.
Segue um exemplo de acesso randômico a arquivo para escrita (criação automática quando não existe) e posterior leitura. É necessário ter uma pasta "c:\temp" em seu PC ou mude este caminho no código:
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class TesteFileChannel {
public static void main(String[] args) {
TesteFileChannel tfc = new TesteFileChannel();
tfc.writeText();
tfc.readText();
}
public void writeText() {
String text = null;
FileChannel rwChannel = null;
MappedByteBuffer rwBuffer = null;
try {
// Texto para guardar
text = "Olá mundo";
// Abre canal de comunicação
rwChannel = new RandomAccessFile("c:/temp/datafile.txt", "rw").getChannel();
// Aloca uma fatia bytes para guardar o texto a partir do canal do arquivo
rwBuffer = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, text.length());
// Coloca o ponteiro na posição ZERO da memória mapeada
rwBuffer.position(0);
// Escreve os bytes do texto no arquivo
rwBuffer.put(text.getBytes(), 0, text.getBytes().length);
// Como o acesso é não bloqueante, neste caso é forçada
// a efetivação escrita caso esteja pendente
rwChannel.force(true);
// Encerra canal de comunicação
rwChannel.close();
// Destrói o objeto representante da memória alocada
rwBuffer.clear();
System.out.println("Concluída a escrita com sucesso: " + text);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readText() {
byte[] bytes = null;
String text = null;
FileChannel rwChannel = null;
MappedByteBuffer rwBuffer = null;
try {
// Abre canal de comunicação
rwChannel = new RandomAccessFile("c:/temp/datafile.txt", "rw").getChannel();
// Aloca uma fatia bytes para guardar o texto a partir do canal do arquivo
rwBuffer = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, rwChannel.size());
// Coloca o ponteiro na posição ZERO da memória mapeada
rwBuffer.position(0);
// Vetor para leitura
bytes = new byte[(int) rwChannel.size()];
// Lê os bytes do texto no arquivo
rwBuffer.get(bytes, 0, bytes.length);
// Converte bytes para texto
text = new String(bytes);
// Encerra canal de comunicação
rwChannel.close();
// Destrói o objeto representante da memória alocada
rwBuffer.clear();
System.out.println("Concluída a leitura com sucesso: " + text);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class TesteFileChannel {
public static void main(String[] args) {
TesteFileChannel tfc = new TesteFileChannel();
tfc.writeText();
tfc.readText();
}
public void writeText() {
String text = null;
FileChannel rwChannel = null;
MappedByteBuffer rwBuffer = null;
try {
// Texto para guardar
text = "Olá mundo";
// Abre canal de comunicação
rwChannel = new RandomAccessFile("c:/temp/datafile.txt", "rw").getChannel();
// Aloca uma fatia bytes para guardar o texto a partir do canal do arquivo
rwBuffer = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, text.length());
// Coloca o ponteiro na posição ZERO da memória mapeada
rwBuffer.position(0);
// Escreve os bytes do texto no arquivo
rwBuffer.put(text.getBytes(), 0, text.getBytes().length);
// Como o acesso é não bloqueante, neste caso é forçada
// a efetivação escrita caso esteja pendente
rwChannel.force(true);
// Encerra canal de comunicação
rwChannel.close();
// Destrói o objeto representante da memória alocada
rwBuffer.clear();
System.out.println("Concluída a escrita com sucesso: " + text);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readText() {
byte[] bytes = null;
String text = null;
FileChannel rwChannel = null;
MappedByteBuffer rwBuffer = null;
try {
// Abre canal de comunicação
rwChannel = new RandomAccessFile("c:/temp/datafile.txt", "rw").getChannel();
// Aloca uma fatia bytes para guardar o texto a partir do canal do arquivo
rwBuffer = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, rwChannel.size());
// Coloca o ponteiro na posição ZERO da memória mapeada
rwBuffer.position(0);
// Vetor para leitura
bytes = new byte[(int) rwChannel.size()];
// Lê os bytes do texto no arquivo
rwBuffer.get(bytes, 0, bytes.length);
// Converte bytes para texto
text = new String(bytes);
// Encerra canal de comunicação
rwChannel.close();
// Destrói o objeto representante da memória alocada
rwBuffer.clear();
System.out.println("Concluída a leitura com sucesso: " + text);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}