Los archivos
Los diferentes archivos
1. Preámbulo
Le pido que por una vez, me permita ser un poco directo: describir los archivos son una calamidad en algoritmia. Durante años, hasta mitad de los años 1990, COBOL fue el rey absoluto entre los lenguajes de programación en informática de gestión. Este lenguaje también era potente en este dominio, porque su sintaxis era práctica. Los que conozcan un poco COBOL sabrán de qué hablo. Una de las fuentes de su potencia era su capacidad de gestionar archivos y registros estructurados en todos los sentidos, en todos los formatos.
COBOL ha pasado de moda para los nuevos desarrollos. La multitud de archivos con datos diversos y variados se han sustituido por otras estructuras, principalmente por bases de datos relacionales, haciendo caduco el estudio de la mayor parte de los tipos de archivos, en beneficio de lenguajes como SQL. Sin embargo, las bases de datos normalmente se almacenan ellas mismas en archivos.
De esta manera, este capítulo es un poco más corto que los otros. Sería posible describir una multitud de tipos de archivos: existen libros completos sobre este tema, con varios centenares de páginas. Se abordan todos los conceptos básicos y las definiciones teóricas.
2. Problemática
¿Qué es un archivo? Es exactamente lo mismo que en la realidad. Cuando tiene un único dato que debe recordar en su cabeza, es fácil. Cuando tiene miles, es una misión imposible. Va a utilizar una agenda, rellena de fichas. El cerebro tiene ciertas capacidades increíbles, pero ¿cómo retener todas las transacciones bancarias de millones de cuentas para un banco?
A esto se añaden los siguientes problemas:
-
A pesar de la potencia de sus ordenadores, la capacidad de memoria normalmente está limitada. Un ordenador de 32 bits "estándar" (de sobremesa o para jugar), está limitado a 4 GB. Con los procesadores de 64 bits, las máquinas van mucho más allá, hasta varios centenares de GB. Incluso en el modesto nivel del ordenador personal, esto en la era digital normalmente es insuficiente: es imposible conservar todos los datos en memoria. Por ejemplo, una película en formato DV de una videocámara ocupa cerca de 20 GB, un DVD completo más de 8 GB, un Blu-ray 25 GB, etc.
-
Aunque fuera posible...
Los registros
Este capítulo se centra en los archivos de texto. En estos, debe definir la estructura de sus registros. Aunque todo sea posible, principalmente con las estructuras en arborescencia como el XML, inicialmente puede elegir entre dos métodos muy sencillos: los registros con delimitadores o de longitud fija.
1. Los delimitadores
Los registros delimitados son habituales en Unix. En cada línea, los valores individuales se llaman campos y están separados entre ellos por un carácter particular llamado carácter de separación o carácter de delimitación o delimitador. Cualquier carácter puede ser conveniente, sin embargo no se debe encontrar en el valor de un campo, lo que tendría por efecto que romper la estructura del registro. Normalmente es el punto y coma ";" o los dos puntos ":" los que se utilizan.
Los campos de registro normalmente se encierran entre comillas cuando se trata de cadenas de caracteres. No se hace nada con los valores numéricos. Esto no es una afirmación: no siempre es el caso y es usted el que debe gestionar el tipo de un valor dado dentro de su programa.
A continuación se muestra un sencillo ejemplo de contenido de archivo delimitado de tipo habitual, en Unix:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:Daemon:/sbin:/bin/bash
lp:x:4:7:Printing daemon:/var/spool/lpd:/bin/bash
mail:x:8:12:Mailer daemon:/var/spool/clientmcola:/bin/false
news:x:9:13:News system:/etc/news:/bin/bash
uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash
Los más perspicaces habrán reconocido un fragmento del archivo Unix /etc/passwd que contiene alguna información de las cuentas de usuarios del sistema Unix. Cada línea es un registro cuya estructura es la siguiente:
-
Un separador ":" delimita los diferentes campos.
-
Hay siete campos, numerados (por convención) de 1 a 7.
-
1er campo: nombre del usuario (su login).
-
2º campo: indicador de la contraseña (aquí almacenado en otro lugar).
-
3º campo: UID, identificador numérico único del usuario.
-
4º campo: GID, identificador del grupo del usuario (almacenado en otro lugar).
-
5º campo: comentario libre.
-
6º campo: directorio personal del usuario.
-
7º campo: el intérprete de comandos...
Archivo de texto secuencial
1. Abrir y cerrar un archivo
En primer lugar, debe declarar el nombre lógico del archivo, la variable asociada al archivo que permitirá trabajar con él. Esto se sitúa en la sección Var como habitualmente. A continuación indique el tipo de acceso: secuencial, directo, indexado, etc. Observe que en el acceso directo, también puede trabajar en modo secuencial.
VAR
arch:archivo secuencial
A continuación debe abrir el archivo, asociando su nombre lógico y el nombre del archivo, con el modo de apertura deseado. Esto se realiza con la instrucción Abrir.
Abrir "toto.txt" en arch en modo lectura
Algunas veces también se encontrará con esta sintaxis en forma de función, más cercana a algunos lenguajes:
arch←Abrir("toto.txt","lectura")
La primera sintaxis es normalmente preferible en algoritmia. Para cerrar un archivo, utilice la instrucción Cerrar seguida del nombre lógico del archivo.
Cerrar arch
También existe una sintaxis funcional, pero se aplican las mismas observaciones: utilice la primera en caso de duda.
Cerrar(arch)
No escriba el nombre del archivo en las instrucciones de lectura, escritura y cierre. El programa no conoce el nombre del archivo, solo su nombre lógico.
De esta manera, el inicio de un eventual programa se parecería a lo siguiente:
Programa APERT
Var
arch:archivo secuencial
nombre:cadena
Inicio
nombre←"toto.txt"
Abrir nombre en arch en modo lectura
/* operaciones */
Cerrar arch
Fin
2. Leer y escribir registros
a. Lectura
Como recordatorio, aquí los registros son las líneas de un archivo de texto, siendo un registro equivalente a una línea. La lectura de una línea se hace con la instrucción Leer. Leer lee el registro presente en la posición actual del archivo y después, se sitúa en el siguiente registro. Durante la apertura del archivo, Leer lee la primera línea. Un nuevo Leer leerá la segunda y así sucesivamente hasta el final. Por este motivo, la lectura se dice que es secuencial. Encontrará también la misma instrucción bajo el nombre LeerArchivo. Es lo mismo.
La sintaxis...
Los archivos binarios
1. Nuevas instrucciones
El acceso a los archivos binarios retoma los mismos principios generales, salvo que esta vez se trata de una sucesión de bytes y no de registros. Por lo tanto, es necesario:
-
Un nuevo modo de apertura de archivo: binario.
-
Una nueva función predeterminada de lectura: LeerByte(arch), que devuelva el valor.
-
Una nueva función predeterminada de escritura: EscribirByte(arch,valor).
-
Una función predeterminada para recuperar el lugar actual: Position(arch).
-
Una función predeterminada para ir a otro lugar: Posicion(arch,pos).
Las otras instrucciones y funciones (Abrir, Cerrar, EOF) siguen siendo válidas.
2. Ejemplo
A continuación se muestra el ejemplo que permite leer un archivo byte por byte y mostrar el carácter ASCII correspondiente y el tamaño del archivo al final:
Programa LEERBINARIO
Var
arch:archivo binario
byte:entero
Inicio
Abrir nombre en arch en modo lectura
MientrasQue NO EOF(arch) Hacer
byte←LeerByte(arch)
Mostrar Caracter(byte)
FinMientrasQue
Mostrar " Tamaño del archivo: ", posicion(arch)
Cerrar arch
Fin
Vamos a encontrarnos exactamente con las mismas funciones para la lectura de un archivo en binario, que para un archivo de texto normal (ASCII). Durante la apertura, el b asociado...
Ejercicios
Ejercicio 1
Escriba el algoritmo COPIA que copia un archivo en otro, byte por byte. Dar el programa Python asociado.
Ejercicio 2
Este ejercicio representa un resumen de los anteriores capítulos y ofrece desarrollar una herramienta completa, práctica y funcional.
El objetivo de este ejercicio es diseñar un programa capaz de leer un archivo byte por byte y mostrar la representación en formato hexadecimal a la izquierda y en el formato ASCII a la derecha. Cada línea mostrará 16 caracteres. Un contador de posición se mostrará a la izquierda del todo. Si el carácter no es imprimible, se sustituirá por un punto.
El formato esperado es el siguiente:
00000000 23 21 2f 62 69 6e 2f 62 61 73 68 0a 0a 5b 20 24 |#!/bin/bash..[ $|
00000010 23 20 2d 6c 74 20 31 20 5d 20 26 26 20 65 78 69 |# -lt 1 ] && exi|
00000020 74 20 31 3b 0a 0a 74 79 70 65 73 65 74 20 2d 69 |t 1;..typeset -i|
Por lo tanto se trata de programar una herramienta de dump del archivo binario en hexadecimal. Puede ayudarse de los diferentes ejemplos y ejercicios abordados...