Translate

sábado, 17 de dezembro de 2011

Java NIO - Acesso randômico a arquivo

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();
        }

    }

}

Nenhum comentário:

Postar um comentário