Após algumas vezes programar rotinas para capturar bytes vindos de conexão socket ou porta serial, armazenar estes bytes e em seguida processá-los para extrair a informação original, percebi logo a complexidade disso.
Qualquer um que já tenha programado um client ou server socket em Java, C++ e C ANSI sabe o que digo, pois utilizar um byte array para armazenar (bufferizar) dados recebidos antes de enquadrar uma informação significativa é uma maneira arcaica e dispensiosa.
Certo dia, resolvi simplificar esta situação com a criação de um mecanismo chamado WTByteBuffer bastante simples para prover apenas dois métodos, um método de escrita e outro de leitura a partir do ByteBuffer do Java NIO.
O método de escrita armazena os bytes lidos e o método de leitura consome os bytes. Desta forma, o programador Java será poupado de todo o trabalho discutido anteriormente para bufferizar e consumir dados recebidos.
WTByteBuffer - Classe para bufferizar
import java.nio.ByteBuffer;
public class WTByteBuffer {
    public static final int DEFAULT_MAX_SIZE = 1024 * 65; 
    private volatile ByteBuffer buffer;
    private int size; 
    private int bufferMaxSize;
    public int getSize() {
        return this.size;
    }
    public ByteBuffer getBuffer() {
        return this.buffer;
    }
    
    
    public WTByteBuffer() {
        this(WTByteBuffer.DEFAULT_MAX_SIZE);
    }
    public WTByteBuffer(int bufferMaxSize) {
        this.bufferMaxSize = bufferMaxSize;
        this.buffer = ByteBuffer.allocate(bufferMaxSize); 
        buffer.position(0);
        this.size = 0;
        
    }
    public synchronized void write(byte[] bytes) {
        if (this.buffer == null) 
            System.out.println("Buffer nulo : W");
        
        this.buffer.put(bytes);
        this.size = this.buffer.position();
        
    }
    public synchronized int read(byte[] bytes) {
        int target, position, newPosition, capacity;
        byte[] completeBuffer = null;
        byte[] remainingBuffer = null;
        if (bytes == null || bytes.length == 0) {
            return 0;
        }
        if (this.buffer == null) 
            System.out.println("Buffer nulo : R");
        target = bytes.length;
        position = this.buffer.position();
        capacity = this.buffer.capacity();
        if (target > position) {
            target = position;
        }
        newPosition = position - target;
        completeBuffer = new byte[position];
        remainingBuffer = new byte[newPosition];
        
        this.buffer.flip();
        this.buffer.get(completeBuffer, 0, position);
        System.arraycopy(completeBuffer, 0, bytes, 0, target);
        this.buffer = null;
        this.buffer = ByteBuffer.allocate(capacity);
        
        if (newPosition > 0) {
            System.arraycopy(completeBuffer, target, remainingBuffer, 0, newPosition);
            this.buffer.put(remainingBuffer);
        }
    
        this.size = this.buffer.position();
    
        return target;
    }
    
    public synchronized void clear() {
        
        if (this.buffer != null) {
            this.buffer.clear();
            this.buffer = null;
        }
        this.buffer = ByteBuffer.allocate(bufferMaxSize); 
        buffer.position(0);
        this.size = 0;
    }    
 
}
Testando um buffer
Este exemplo cria uma instância de WTByteBuffer com 100 bytes de capacidade, escreve a série de bytes de um texto qualquer e recupera de um em um byte. Depois repete o teste recuperando de dois em dois bytes do texto bufferizado.
        WTByteBuffer buffer = new WTByteBuffer(100);
        String text = "ABXYZ-0123456-abc";
        
        byte[] read = new byte[2];
        byte[] serialized = text.getBytes();
        int size = 0;
        System.out.println("-----------------------------------------");
        buffer.write(serialized);
        System.out.format("Texto guardado em buffer: %s\n", text);
        
        System.out.println("Recupera texto de 1 em 1 byte...");
        
        while (buffer.getSize() > 0) {
            read = new byte[1];
            size = buffer.read(read);
            System.out.format("1 byte lido: %s\n", new String(read));
        }
        System.out.format("Bytes guardados: %d\n", buffer.getSize());
        System.out.println("-----------------------------------------");
        buffer.write(serialized);
        System.out.format("Texto guardado em buffer: %s\n", text);
        
        System.out.println("Recupera texto de 2 em 2 byte...");
        
        while (buffer.getSize() > 0) {
            read = new byte[2];
            size = buffer.read(read);
            System.out.format("%d byte(s) lido(s): %s\n", size, new String(read));
        }
        
        buffer = null;
Numa situação real a capacidade deste buffer deverá ser maior do que 100. Caso desejar aumentar o tamanho, faça isso ao construir o WTByteBuffer ou então utilize o construtor padrão para iniciar com o tamanho padrão de reserva máxima.
A classe abordada ainda provê métodos adicionais para controle e acesso ao buffer central.
Boa sorte.
 
 
 
Nenhum comentário:
Postar um comentário