|
I/O: Leer y Escibir |
Escribir Filtros para Ficheros de Acceso Aleatorio
Reescribamos el ejemplo de Escribir Nuestros Propios Streams Filtrados para que funcione sobre RandomAccessFiles. Como RandomAccessFile implementa los interfaces DataInput y DataOutput, un beneficio lateral es que los streams filtrados también funcionan con otros streams DataInput y DataOutput incluidos algunos streams de acceso secuencial como DataInputStream y DataOutputStream.
El ejemplo CheckedIOTest de Escribir Nuestros Propios Streams Filtrados implementa dos streams filtrados, CheckedInputStream y CheckedOutputStream, que calculan un checksum de los datos que son leídos o escritos en el stream.
El nuevo ejemplo, CheckedDataOutput es una re-escritura de CheckedOutputStream--calcula un checksum para los datos escritos en el stream-- pero opera sobre objetos DataOutput en lugar de sobre objetos OutputStream. De forma similar CheckedDataInput modifica CheckedInputStream para que ahora funciona sobre objetos DataInput en lugar de objetos InputStream.
CheckedDataOutput contra CheckedOutputStream
Echemos un vistazo a las diferencias entre CheckedDataOutput y CheckedOutputStream.
La primera diferencia es que CheckedDataOutput no desciende de FilterOutputStream. En su lugar, implementa el interface DataOutput.
public class CheckedDataOutput implements DataOutput
|
Nota:
Para mantener el ejemplo sencillo, la clase CheckedDataOutput realmente proporcionada en esta sección no está declarada para implementar DataOutput, porque el interface DataOutput especifica demasiados métodos. Sin embargo, la clase CheckedDataOutput proporcionada en el ejemplo implementa varios métodos de DataOutput para ilustrar como deberían funcionar. |
Luego, CheckedDataOutput declara una variable privada para contener un objeto DataOutput.
private DataOutput out;
Este es el objeto en el se escribirán los datos.
El constructor para CheckedDataOutput es diferente del constructor de CheckedOutputStream: CheckedDataOutput se crea sobre un objeto DataOutput en vez sobre un objeto OutputStream.
public CheckedDataOutput(DataOutput out, Checksum cksum) {
this.cksum = cksum;
this.out = out;
}
Este constructor no llama a super(out) como hacía el constructor de CheckedOutputStream. Esto es porque CheckedDataOutput desciende de Object en vez de la clase stream.
Aquí están las únicas modificaciones echas a CheckedOutputStream para crear un filtro que funcione sobre objetos DataOutput.
CheckedDataInput contra CheckedInputStream
CheckedDataInput requiere los mismos cambios que CheckedDataOuput.
- CheckedDataInput no desciende de FilterInputStream pero implementa el interface DataInput.
Nota: Para mantener el ejemplo sencillo, la clase CheckedDataInput realmente proporcionada en esta sección no está declarada para implementar DataInput, porque el interface DataInput especifica demasiados métodos. Sin embargo, la clase CheckedDataInput proporcionada en el ejemplo implementa varios métodos de DataInput para ilustrar como deberían funcionar.
- CheckedDataInput declara una variable privada para contener un objeto DataInput que lo envuelve.
- El constructor de CheckedDataInput requiere un objeto DataInput en vez de un objeto InputStream.
Además de estos cambios, el método read también se ha modificado. El CheckedInputStream del ejemplo original implementa dos métodos read, uno para leer un sólo byte y otro para leer un array de bytes. El interface DataInput teine métodos que implementan la misma funcionalidad, pero tienen diferentes nombres y firmas de métodos. Así el método read de la clase CheckedDataInput tiene nuevos nombres y firmas de métodos.
public byte readByte() throws IOException {
byte b = in.readByte();
cksum.update(b);
return b;
}
public void readFully(byte[] b) throws IOException {
in.readFully(b, 0, b.length);
cksum.update(b, 0, b.length);
}
public void readFully(byte[] b, int off, int len)
throws IOException
{
in.readFully(b, off, len);
cksum.update(b, off, len);
}
Los Programas Principales
Finalmente, este ejemplo tiene dos programas principales para probar los nuevos filtros. CheckedDITest, que ejecuta el filtro sobre ficheros de acceso secuencial (objetos DataInputStream y DataOutputStream), y CheckedRAFTest, que ejecuta los filtros sobre ficheros de acceso aleatorio (objetos RandomAccessFiles).
Estos dos programas se diferencian sólo en el tipo del objeto que abren para el filtro. CheckedDITest crea un DataInputStream y un DataOutputStream y usa el filtro checksum sobre ellos, como en el siguiente código:
cis = new CheckedDataInput(
new DataInputStream(new FileInputStream("farrago.txt")),
inChecker);
cos = new CheckedDataOutput(
new DataOutputStream(new FileOutputStream("outagain.txt")),
outChecker);
CheckedRAFTest crea dos RandomAccessFiles, uno para leer y uno para escribir, y usa el filtro checksum sobre ellos.
cis = new CheckedDataInput(
new RandomAccessFile("farrago.txt", "r"),
inChecker);
cos = new CheckedDataOutput(
new RandomAccessFile("outagain.txt", "rw"),
outChecker);
Cuando ejecutemos cualquiera de estos programas deberíamos ver la siguiente salida:
Input stream check sum: 736868089 Output stream check sum: 736868089
















































