Sin duda son las instrucciones mas importantes con las que cuenta el lenguaje Cobol, con ellas tendremos la oportunidad de manipular toda la información contenida en nuestros archivos, es decir, podremos abrir archivos, cerrarlos, leerlos, guardar información nueva o modificar datos existentes. Todo ésto lo haremos con las instrucciones que voy a explicar a continuación.
Antes de empezar a explicar éstas instrucciones me gustaría que entendiéseis bien algunos conceptos como fichero, registro y campo, para que podais comprender mas claramente, la explicación de todas las instrucciones que se verán en ésta sección.
- ¿Que es un fichero? Podríamos definir un fichero como un conjunto de registros, pero estaríamos mas o menos igual. Si comparásemos un fichero de cobol con nuestra vieja agenda de teléfonos, para cada amigo tendríamos los mismos datos, es decir, nombre, teléfono, dirección, etc … cada uno de esos datos es lo que llamamos campo y el conjunto de todos esos campos para cada amigo sería un registro. Ahora podemos comprender mejor que un fichero o archivo es un conjunto de registros, como una agenda es un conjunto de datos de amigos.
- ¿Que es una clave? Una clave, es un campo de nuestra agenda que nos sirve para identificar a cada amigo, en la agenda normal la clave podría ser la lengüeta con la letra del abecedario correspondiente a los apellidos del amigo. Informáticamente es mas completa y con ella podremos identificar a cada uno de ellos, por ejemplo con su nombre o su teléfono o un código que le asignemos nosotros personalmente.
En Temáticos trataremos el tema de los ficheros en mas profundidad.
OPEN, ésta es la instrucción que utilizaremos para abrir un archivo, o lo que es lo mismo hacerlo disponible para operar sobre el, obviamente éste archivo debe de haberse descrito en la Environment y la Data según se explicó, su formato es el siguiente:
OPEN (EXCLUSIVE ) modo nombre de archivo ( WITH LOCK) (WITH NO REWIND)
Donde modo, indica como se abrirá el archivo y puede tener los siguientes valores según su utilización:
- INPUT, el archivo se abrirá solo para lectura, es decir no podremos grabar ni modificar datos del mismo.
- I-O, el archivo se abrirá como lectura y escritura, con lo cual tendremos acceso a toda la información de dicho archivo para leerla, escirbirla, reescribirla o borrarla.
- OUTPUT, el archico se abre solo para escritura, es el formato que se utiliza en los achivos de impresión y secuenciales. Tiene la particularidad que crea el fichero nuevo cada vez que se utiliza, por lo tanto hay que tener cuidado con archivos Indexados.
- EXTEND, igual que el anterior pero no crea el archivo, sino que la información se va añadiendo a la ya existente. Se utiliza para archivos secuenciales.
Las opciones EXCLUSIVE y WITH LOCK, nos indica cuando trabajamos en multipuesto que éste archivo estará bloqueado, es decir que no estará disponible para otros usuarios. El hecho de que existan dos opciones para lo mismo es por compatibilidad con versiones anteriores.
La opción WITH NO REWIND, se utiliza cuando utilizamos archivos de cinta, para que no la rebobine al abrirla.
… PROCEDURE DIVISION. INICIO. OPEN INPUT ARTICULOS. OPEN I-O CLIENTES OPEN EXTEND IMPRE. CREAR-ARCHIVO. OPEN OUTPUT TRABAJO CLOSE TRABAJO. … |
|
Nota: Con éstas tres instrucciones estamos abriendo tres archivos, cada uno de una forma diferente. Tambien podriamos haberlos puesto en una sola linea de la siguiente forma: OPEN INPUT ARTICULOS I-O CLIENTES EXTEND IMPRE. En el caso del archivo TRABAJO, se consigue crearlo como nuevo, exista antes o no. |
CLOSE, ésta es la instrucción contraria a OPEN, es decir termina la conexión establecida con el archivo, a partir del momento que aparezca ésta instrucción el archivo no estará disponible para operar con él, hasta la próxima vez que se abra. Obviamente antes de cerrarlo debe de estar abierto.
CLOSE nombre de archivo ( WITH LOCK) (WITH NO REWIND )
El nombre de archivo corresponderá a algún archivo abierto anteriormente.
Las opciones WITH LOCK y WITH NO REWIND , tienen la misma explicación que la vista en la orden OPEN.
… PROCEDURE DIVISION. INICIO. OPEN INPUT ARTICULOS. OPEN I-O CLIENTES OPEN EXTEND IMPRE. … … … CERRAR. CLOSE ARTICULOS CLIENTES IMPRE. … |
|
Nota: Apuntaré que si finalizamos el programa con la sentencia STOP RUN, que luego veremos, los archivos que estuvieran abiertos se cierran automáticamente aunque no se haya especificado la orden CLOSE. Anque siempre es preferible utilizarla, ya que puede haber algunos compiladores mas antiguos que no los cierren. Me gustraría destacar de éstas dos instrucciones vistas que lo mas normal es no utilizar ninguna de las opciones, es decir solo abrir de una manera el archivo para su uso y una vez hayamos acabado con él, cerrarlo. |
READ, es la instrucción que utilizamos para leer registros de un archivo, debe de estar abierto. Con ella conseguimos que los datos referentes al registro accedido queden en la descripción de dicho fichero, es decir, conseguimos que los campos declarados en la FD, tengan el valor correspondiente al registro leido.
La sentencia READ, se utiliza para leer ficheros secuanciales o indexados, o para leer indexados de manera secuencial, por lo que su sintaxis tiene dos formatos principales.
Formato para leer ficheros de manera secuncial. (Indexados o secuenciales)
READ nombre de archivo ( NEXT/PREVIOUS RECORD) ( INTO descripción) (AT END / NO AT END sentencia) END-READ
nombre de archivo corresponderá a algún archivo abierto anteriormente.
La opción NEXT RECORD, indica que se va a leer el siguiente registro y es la que se toma por defecto, ya que, cuando estamos leyendo un archivo de forma secuencial, éste leerá registros uno tras otro, hasta llegar al final.
La opción PREVIOUS RECORD leería el registro anterior. Esta opción es la única que no es válida para ficheros secuenciales de éste formato.
La opción INTO, indica cual de las descripciones de registro que hayamos podido declarar será la que almacene los datos del registro leido. Tenemos que tener en cuenta que Cobol nos permite mantener mas de una descripción de registro para un mismo archivo. Si tuvieramos mas de una, ésta sería la opción para indicarle cual es la que queremos utilizar en ésta lectura.
La sentencia que va después de AT END , indica que debe de hacer el programa al llegar al final del fichero. Puede ser cualquier orden de cobol, pero es evidente que si volvemos a leer una vez llegado al final, producirá un error.
… PROCEDURE DIVISION. INICIO. OPEN INPUT ARTICULOS. LECTURA. READ ARTICULOS NEXT RECORD AT END GO CERRAR. … … … GO LECTURA. CERRAR. CLOSE ARTICULOS. … |
|
Nota: Si bien este formato nos sirve para leer cualquier tipo de archivo de manera secuencial, en el caso de que el archivo fuera secuencial, éste solo se podría leer así. Existen muchas ocasiones en que un archivo indexado nos interesa leerlo de manera secuencial. Si lo hicieramos éste sería su formato, además en éste caso podriamos leerlo tanto del principio al final con la opción NEXT, como del final al principio con la opción PREVIOUS. Para poder leer un fichero indexado de manera secuencial, deberemos de haber especificado en la SELECT, que su acceso va a ser DYNAMIC o SEQUENTIAL. |
Formato para leer ficheros indexados con acceso aleatorio.
READ nombre de archivo (INTO descripción) (KEY nombre de clave) ( INVALID KEY / NOT INVALID KEY sentencia) END-READ
Las opciones que se repiten con con el formato anterior tienen el mismo formtato y producen el mismo resultado.
La opción KEY, indica por que clave se va a leer el fichero, siempre que éste tenga mas de una.
La sentencia después de INVALID KEY se utiliza para ejecutar una acción cuando se intenta acceder a un registro que no existe. En el caso de utilizar NOT INVALID KEY sería al contrario, es decir cuando el registro existe.
… PROCEDURE DIVISION. INICIO. OPEN INPUT ARTICULOS. LECTURA. MOVE 100 TO CLAVE-ARTICULO. READ ARTICULOS INVALID KEY GO ERROR. … … … GO LECTURA. ERROR. … … CERRAR. CLOSE ARTICULOS. … |
|
Nota: Sin duda la forma mas usual de acceder a un registro será por su clave. Asi por ejemplo para acceder a un fichero de poblaciones cuya clave fuera su código postal, dando cualquier código accederiamos a ese registro en concreto. La acción que hagamos después de un INVALID KEY, dependerá del contexto en que se encuentre, podremos volver a solicitar otra clave, permitir crear un registro, etc .. |
WRITE, con ésta instrucción se consigue grabar la información contenida en ese momento en los campos del registro de un fichero. Es decir, si introducimos una ficha nueva en la agenda con los datos de un nuevo amigo, ésta instrucción será la que nos sirva para almacenar en el fichero los datos. A partir de ese momento estarán disponibles tantas veces como queramos para leerla. Y por supuesto el fichero debe de estar abierto como OUTPUT o I-O.
WRITE nombre de registro ( FROM descripción) ( INVALID KEY / NOT INVALID KEY sentencia)
END-WRITELa opción FROM, indica con cual de las descripciones de registro que hayamos podido declarar se graben los datos en el fichero. Hay que señalar que ésta descripción puede estar definida en la WORKING, y lo que nos ahorra en realidad es mover los datos de esa descripción que hemos usado como «temporal» a la auténtica descripción del registro.
Las cláusulas de INVALID KEY y NOT INVALID KEY, tienen la misma función dada en la instrucción READ. Solo que aqui, INVALID KEY , se produciría cuando al grabar el registro, éste ya existiese o hubiera algún error por el cual no se pudieran grabar los datos.
… PROCEDURE DIVISION. INICIO. OPEN I-O ARTICULOS. LECTURA. MOVE 100 TO CLAVE-ARTICULO. MOVE «ANDRES MONTES» TO NOMBRE. WRITE REGISTRO-ARTICULO INVALID KEY GO ERROR. … … GO CERRAR. ERROR. … … CERRAR. CLOSE ARTICULOS. … |
|
Nota: Aunque se puedan utilizar varias descripciones, lo mas lógico es utilizar siempre la misma para cada fichero. El error mas probable siempre que sea una INVALID KEY, suele ser que existe un registro ya con esa clave, a parte de ese, falta de espacio en disco, archivo mal abierto o sin abrir. |
Además de éste formato, existe para ésta instrucción otro muy común. Y es el que utilizamos para enviar datos a la impresora, es decir para listar, para imprimir.
Es en éste caso, donde se hace indispensable el uso de mas de una descripción por registro. ¿Porque? Sencillo, definiremos nuestro fichero con un registro de tamaño igual al ancho de nuestro listado, y luego en la WORKING, describiremos el formato de cada una de las lineas que utilizaremos en la impresión. Quiero hacer un ejemplo mas extenso para éste caso, que será muy utilizado y distinto en su filosofía al resto.
WRITE nombre de registro ( FROM descripción) ( AFTER número de lineas)(PAGE) END-WRITE
Además para éste formato tendremos la cláusula AFTER, en la cual indicamos el número de lineas que debe de avanzar la impresora antes de escribir, o bien que lo haga directamente al principio de la siguiente página, poniendo AFTER PAGE. Existen algunas otras cláusulas, pero no las vamos a ver aquí por ser poco usadas.
IDENTIFICATION DIVISION. PROGRAM-ID. LISTADO. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT IMPRESORA ASSIGN TO PRINT «LPT1». DATA DIVISION. FILE SECTION. FD IMPRESORA LABEL RECORD OMITTED. 01 REG-IMPRE PIC X(80). WORKING-STORAGE SECTION. 01 LINEA1. 02 FILLER PIC X(30) VALUE SPACES. 02 FILLER PIC X(20) VALUE «ESTA ES LA LINEA 1». 01 LINEA2. 02 FILLER PIC X(30) VALUE SPACES. 02 FILLER PIC X(20) VALUE «ESTA ES LA LINEA 2». … … PROCEDURE DIVISION. INICIO. OPEN OUTPUT IMPRESORA ESCRIBIR. WRITE REG-IMPRE FROM LINEA1 AFTER PAGE. WRITE REG-IMPRE FROM LINEA2 AFTER 2. … … CERRAR. CLOSE IMPRESORA. … |
|
Nota: Como podeis ver, hemos definido el registro como REG-IMPRE, pero al escribir sobre el fichero impresora utilizamos las descripciones de LINEA1 y LINEA2, de ésta manera conseguimos que se impriman las dos lineas en una impresora conectado al puerto LPT1 y que antes de escribir la primera linea, salte a una página en blanco. |
REWRITE, ésta instrucción se utiliza para regrabar datos de un registro ya existente. Toda la sintaxis es exactamente igual que la explicada en WRITE.
REWRITE nombre de registro ( FROM descripción) ( INVALID KEY / NOT INVALID KEY sentencia) END-REWRITE
Todas las opciones igual que en WRITE. Por lo que en el ejemplo vamos a ver ambos casos juntos.
… PROCEDURE DIVISION. INICIO. OPEN I-O ARTICULOS. LECTURA. MOVE 100 TO CLAVE-ARTICULO. MOVE «ANDRES MONTES» TO NOMBRE. WRITE REGISTRO-ARTICULO INVALID KEY GO ERROR. MOVE «OTRO NOMBRE» TO NOMBRE. REWRITE REGISTRO-ARTICULO INVALID KEY GO ERROR. … … GO CERRAR. ERROR. … … CERRAR. CLOSE ARTICULOS. … |
|
Nota: Podemos decir que ésta sentencia es la que utilizaremos para modificar el contenido de cualquier registro, pero eso si, nunca podremos alterar la clave, solo los campos que no formen parte de la clave principal. Si quisieramos modificar cualquiera de los campos clave de un registro, deberíamos crear uno nuevo con el mismo contenido pero con la clave que ahora queramos y luego borrar el que teníamos. |
DELETE, instrucción para borrar un registro de un fichero. La explicación es corta, pero tiene pocos mas matices, lo que conseguimos es borrar todos los datos de un registro. Su sintaxix es la siguiente:
DELETE nombre de fichero ( INVALID KEY / NOT INVALID KEY sentencia) END-DELETE
Las únicas cláusulas INVALID y NOT INVALID KEY, se usan exactamente igual que en las demás relativas a ficheros, es decir ejecutará la sentencia que pongamos a continuación cuando una de las condiciones se cumpla, que la clave exista o que no exista.
Si nos fijamos vemos que la gran diferencia está en que aquí la orden hace referencia al nombre del fichero y no al del registro, como en las instrucciones anteriores.
… PROCEDURE DIVISION. INICIO. OPEN I-O ARTICULOS. LECTURA. MOVE 100 TO CLAVE-ARTICULO. READ ARTICULOS INVALID KEY GO ERROR. DELETE ARTICULOS INVALID KEY GO ERROR. … … GO CERRAR. ERROR. … … CERRAR. CLOSE ARTICULOS. … … |
|
Nota: Obviamente para borrar un registro, primero hemos de tenerlo en memoria, por eso en el ejemplo lo he leido primero. |
START, ésta instrucción es de suma importancia en el tratamiento de ficheros, y nos sirve para posicionarnos en cualquier parte del mismo, para una lectura mas rápida. Si imaginamos un fichero con 10.000 clientes, clasificados por código, para ver todos los que cuyo código es mayor a 9.000, tendríamos que leernos el fichero secuencialmente hasta llegar al sitio correcto, en cambio con ésta orden, podremos colocarnos en la posición del fichero que queramos dentro de unas normas, que veremos a continuación.
START nombre de fichero KEY (expresión) nombre de clave ( INVALID KEY / NOT INVALID KEY sentencia) END-START
Las únicas cláusulas INVALID y NOT INVALID KEY, se usan exactamente igual que en las demás relativas a ficheros, es decir ejecutará la sentencia que pongamos a continuación cuando una de las condiciones se cumpla, que la clave exista o que no exista.
Si nos fijamos vemos que la gran diferencia está en que aquí la orden hace referencia al nombre del fichero y no al del registro, como en las instrucciones anteriores.
La expresión a la que se hace referencia en la sintaxis, pueden ser las siguientes:
- LESS (<) menor que.
- NOT LESS (NOT <) no menor que.
- EQUAL (=) igual a.
- GREATER (>) mayor que.
- NOT GREATER (NOT >) no mayor que.
- GREATER OR EQUAL (>=) mayor o igual que.
- LESS OR EQUAL (<=) menor o igual que.
- FIRST principio de fichero (RM/COBOL).
- LAST final del fichero (RM/COBOL).
… PROCEDURE DIVISION. INICIO. OPEN I-O ARTICULOS. COLOCAR. MOVE 100 TO CLAVE-ARTICULO. START ARTICULOS KEY NOT LESS KEY CLAVE-ARTICULOS INVALID KEY GO ERROR. LECTURA. READ ARTICULOS NEXT RECORD AT END GO CERRAR. … GO LECTURA. ERROR. … … GO CERRAR. ERROR. … … CERRAR. CLOSE ARTICULOS. … … |
|
Nota: Aqui empezariamos a leer el ficher artículos desde la clave que no sea menor que 100, es decir de 100 en adelante. Fijaros como luego la lectura se hace en otro párrafo diferente, ya que sino, siempre estariamos haciendo el START. Recordad que con ésta instrucción SOLO nos situamos en un sitio determinado del fichero, a partir de ahí podremos operar como queramos. |
RESUMIENDO
En la programación estructurada es conveniente sustituir el punto como final de una instrucción por la cláusula END-……. para cada instrucción. De esta manera conservamos la estructura y no obligamos con el punto a finalizar ninguna instrucción o bucle en el que estemos metidos.
Una vez vistas todas las intrucciones relativas a ficheros, quiero dejar bien claro su utilización.
Tendremos siempre en cuenta que cuando leemos, realmente le damos el valor del registro que hemos leido a los campos o variables que lo componen. Que cuando grabamos o regrabamos, le estamos dando el valor de las variables en ese momento al registro para que se grabe en disco y cuando borramos, estamos quitando fisicamente del disco esa información.
He realizado un temático dedicado integramente al uso de ficheros, podéis echarle un vistazo por si os han quedado dudas. Temáticos