La interfaz SeekableByteChannel, introducida en Java 7, proporciona una abstracción para operaciones de lectura y escirtura en secuencias de bytes que permiten el posicionamiento aleatorio. Es importante destacar que la escritura en una posición dada no realiza una inserción, sino una sobreescritura de los bytes existentes. La escritura al final del flujo sí incrementa su tamaño.
java.nio.channels.SeekableByteChannel
Una interfaz para canales de bytes que mantienen una posición actual y permiten modificarla.
Un canal de bytes con capacidad de posicionamiento (seekable) se conecta a una entidad, típicamente un archivo, que contiene una secuencia de bytes de longitud variable<br></br>que puede ser leída y escrita. La posición actual puede ser consultada y modificada. El canal también proporciona acceso al<br></br>tamaño actual de la entidad a la que está conectado. El tamaño aumenta cuando se escriben bytes más allá de su<br></br>tamaño actual; el tamaño disminuye cuando la entidad es truncada.
Los métodos `position` y `truncate`, que de otro modo no tendrían un valor de retorno, están especificados para devolver el<br></br>canal sobre el que son invocados. Esto permite encadenar invocaciones de métodos. Las implementaciones de esta interfaz deben<br></br>especializar el tipo de retorno para que las invocaciones de métodos en la clase de implementación puedan ser encadenadas.
La clase FileChannel es una implementación concreta de esta interfaz diseñada para trabajar con archivos:
java.nio.channels.FileChannel
Un canal para leer, escribir, mapear y manipular un archivo.
Un canal de archivo (FileChannel) es un SeekableByteChannel conectado a un archivo. Tiene una posición actual dentro de su archivo que<br></br>puede ser consultada y modificada. El archivo en sí contiene una secuencia de bytes de longitud variable que puede ser leída y<br></br>escrita, y cuyo tamaño actual puede ser consultado. El tamaño del archivo aumenta cuando se escriben bytes más allá de su<br></br>tamaño actual; el tamaño del archivo disminuye cuando es truncado. El archivo también puede tener metadatos asociados,<br></br>como permisos de acceso, tipo de contenido y fecha de última modificación; esta clase no define métodos para acceder a estos metadatos.
A continuación se muestra un ejemplo de uso:
Path rutaArchivo = Paths.get("D://registro.log");
ByteBuffer bufferDatos = ByteBuffer.allocate(1024);
bufferDatos.put("datosEjemplo".getBytes());
bufferDatos.flip();
try {
FileChannel canal = FileChannel.open(rutaArchivo, StandardOpenOption.WRITE);
canal.position(150); // Sobrescribe el contenido en esta posición
canal.write(bufferDatos);
canal.close();
bufferDatos = ByteBuffer.allocate(1024);
canal = FileChannel.open(rutaArchivo, StandardOpenOption.READ);
canal.position(200); // Lee el contenido desde esta posición
canal.read(bufferDatos);
bufferDatos.flip();
System.out.println("Buffer en crudo: " + bufferDatos);
Charset codificacion = Charset.forName("UTF-8");
CharsetDecoder decodificador = codificacion.newDecoder();
CharBuffer bufferCaracteres = decodificador.decode(bufferDatos);
System.out.println("Texto decodificado: " + bufferCaracteres);
} catch (IOException ex) {
ex.printStackTrace();
}
El ejemplo anterior incluye la conversión de un ByteBuffer a un CharBuffer, es decir, de bytes a caracteres, lo que requiere el uso de un decodificador con la codificación correspondiente (CharsetDecoder).