Artigo Originalmente publicado na webMobile 05

 

RONG>Clique aqui para ler todos os artigos desta edição

 

 

Implementando persistência com fluxos em J2ME

Antonio Eloi de Sousa Júnior

No artigo anterior sobre persistência com J2ME, foram apresentadas todas as APIs necessárias para o armazenamento e recuperação de informações em um dispositivo móvel. Porém, a técnica exposta nesse mesmo artigo tratava apenas da persistência de texto puro, onde um registro era manipulado como uma unidade de informação indivisível não havendo, pelo menos de forma natural, a possibilidade de trabalhar com o armazenamento de tipos de dados diferentes no mesmo registro.

Nesse artigo, faremos uso de técnicas de armazenamento e recuperação que permitirão que um registro contenha tipos de dados Java diferentes. Assim, valores do tipo inteiro, string e booleanos poderão formar um registro único em um repositório mantido pelo Record Management System (RMS). Os conceitos de gravação, leitura, navegação, ordenação e filtro serão substancialmente revistos, juntamente com seus respectivos exemplos, para apresentar a utilização de fluxos.

Fluxos de entrada e saída

Os fluxos permitem estabelecer canais de comunicação entre aplicativos e arquivos ou um dispositivo específico. Quando um aplicativo precisa interagir com dispositivos de entrada ou saída ou executar operações de leitura e escrita em um arquivo, um fluxo de dados tem que ser aberto para permitir essa comunicação. Exemplos reais de fluxos são os objetos System.in e System.out que são instanciados automaticamente quando da execução de um aplicativo Java. O objeto System.in representa o fluxo padrão de entrada, normalmente definido como o teclado. O objeto System.out representa o fluxo de saída  padrão de qualquer aplicativo Java e permite, por exemplo, o redirecionamento da sua saída de um dispositivo de vídeo para um arquivo em disco.

Assim, as tarefas de leitura e gravação de registros, realizadas pelos métodos do RMS, também podem ser vistas como atividades de fluxo de dados. O ponto importante é que esse modelo de fluxo de dados manipula apenas bytes, na sua forma primária, e para  tal estávamos trabalhando apenas com o tipo string, convertendo uma string para um array de bytes e vice-versa. É exatamente nesse ponto que utilizaremos classes de controle de fluxos de dados para permitir a persistência de outros tipos de dados.

Para escrever dados, dois fluxos são abertos: um para manipular tipos de dados Java e outro para, a partir desses dados, gerar um array de bytes pronto para enviar para o repositório. No caso da leitura de dados, basta seguir o processo inverso. Veja na Figura 1 o uso do Modelo 1 de gravação, sem as classes de fluxos (artigo publicado na edição 3 da Web Mobile) e o Modelo 2 utilizando as classes de fluxos. A Figura 2 representa visualmente o processo de leitura no RR com e sem as classes de fluxos, respectivamente Modelo 1 e Modelo 2.

Figura 1. Dois modelos de gravação no RR.

image001.png 

 

image003.png

          

Figura 2. Dois modelos de leitura no RR.

 

As classes que implementam os fluxos de entrada e saída que iremos utilizar nesse artigo são: ByteArrayInputStream, DataInputStream, ByteArrayOutputStream e DataOutputStream. Elas estão definidas no pacote java.io que é parte da CLDC (Configuração de Dispositivo Conectado Limitado). Um dos objetivos da CLDC é definir um conjunto mínimo de classes Java que atendam a uma especificação de uma JVM, de tal forma que suporte uma ampla variedade de dispositivos com memória, recursos de vídeo, conectividade e processamento limitado. Os pacotes de classes da CLDC estão presentes também no J2SE, tornando, portanto, todo o conhecimento adquirido na utilização delas nesse ambiente passível de ser reaproveitado no J2ME.

A classe ByteArrayOutputStream estende a classe abstrata OutputStream (superclasse de todas as classes que efetuam fluxo de saída de bytes) e implementa um fluxo de saída, em que os dados são escritos em um buffer representado por um array de bytes. Esse buffer cresce automaticamente à medida que os dados são escritos no fluxo. Veja na Tabela 1 alguns métodos da classe ByteArrayOutputStream.

 

Tabela 1. Alguns métodos da classe ByteArrayOutputStream.

Funcionalidade

Método Correspondente

Fecha o fluxo de saída e libera qualquer recurso associado com o mesmo.

void close()

Reinicializa o campo count do array de bytes do fluxo de saída para zero, descartando qualquer dado acumulado no fluxo.

void reset()

Retorna o tamanho atual do buffer de dados.

int size()

Cria e retorna um novo array de bytes que representa o conteúdo do buffer do fluxo.

byte[] toByteArray()

 

A classe ByteArrayInputStream mantém um buffer interno de bytes para serem lidos em um fluxo de entrada. ByteArrayInputStream estende a superclasse abstrata InputStream. Na Tabela 2 podem ser vistos alguns métodos dessa classe.

 

Tabela 2. Alguns métodos da classe ByteArrayInputStream.

Funcionalidade

Método Correspondente

Fecha o fluxo de entrada e libera qualquer recurso associado com o mesmo.

void close()

Reinicializa o buffer do fluxo de entrada, descartando qualquer dado acumulado no fluxo.

void reset()

Retorna o número de bytes de entrada total que ainda podem ser lidos no fluxo.

int available()

 

No contexto de persistência de dados, a classe DataOutputStream complementa a funcionalidade de ByteArrayOutputStream, fornecendo uma maneira eficiente de escrever tipos primitivos Java no seu buffer de saída em um formato portável entre plataformas. Assim, dados escritos com DataOutputStream em uma determinada plataforma, podem ser lidos com DataInputStream em qualquer outra.

As Tabelas 3 e 4 conceituam, respectivamente, alguns métodos das classes DataOutputStream e DataInputStream.

 

Tabela 3. Métodos da classe DataOutputStream.

Funcionalidade

...

Quer ler esse conteúdo completo? Tenha acesso completo