Archivos de acceso aleatorio

Los archivos de acceso aleatorio nos permiten ir directamente a recuperar el registro deseado, sin necesidad de leer antes todos los anteriores. Solucionan de esta manera la principal limitación de los archivos de acceso secuencial, que era precisamente su método de acceso a los datos, la necesidad de recorrer todo el fichero desde el principio hasta llegar al punto que nos interesaba. Esta limitación se hacia cada vez más grande, según aumentaba el tamaño de nuestro fichero. Con un alto número de registros, los tiempos de lectura podían extenderse demasiado, hasta el punto de ser muy poco operativos y propiciar la migración a un fichero de acceso aleatorio.

Es importante reseñar que nuestra “base de datos”, si puede llamarse así, continuaba siendo un fichero.

He dicho antes que en los archivos de acceso aleatorio, podíamos ir directamente a recuperar el registro deseado, sin necesidad de leer antes todos los anteriores. Para ello era necesario conocer exactamente en que posición, dentro del archivo, se encontraba el registro que buscábamos. Pero.., ¿Cómo era posible saber en que posición se encontraba un registro?.

Básicamente, empleando dos reglas:

  • La longitud de registro estaba estrictamente definida. Es decir, todos los registros tenían la misma longitud, ocupaban el mismo espacio en memoria.
  • Y se emplea el número de registro, para posicionarnos en el registro deseado.

Siguiendo estas sencillas reglas, resultaba muy fácil saber en que posición de memoria comenzaba un registro. Supongamos que cada registro ocupaba 50 bytes, si queremos recuperar el registro 5 teníamos que irnos a leer a la posición 201 y acabábamos en la 250 (el registro 1 se extendería de la posición 1 a la 50, el registro 2 de la 51 a la 100, el 3 de la 101 a la 150, el 4 de la 151 a la 200, y finalmente el registro 5, de la posición 201 a la 250).

Características de los archivos de acceso aleatorio

Después de lo visto en el ejercicio anterior, ya tenemos que ser capaces de apuntar las principales características de los archivos de datos de acceso aleatorio:

  • Longitud fija de registro: Definimos una longitud de datos fija para cada campo y por extensión, para el registro.
  • Posicionamiento instantáneo al principio del registro a recuperar: No hay que recorrer el fichero desde el principio, como ocurría con los archivos de acceso secuencial.
  • Admiten apertura mixta: Podemos abrir el fichero de forma que soporte los modos de escritura y lectura, a la vez.
  • Admite acceso multiusuario: Si bien requiere que se establezcan zonas especificas y limitadas para que los distintos accesos estén controlados, y no se pisen unos a otros, este tipo de acceso permite que varios usuarios trabajen sobre el fichero de manera simultánea.
  • Dimensionamiento máximo del fichero: Al trabajar con una estructura de longitud fija de registros, lo habitual es fijar el número máximo de registros que puede almacenar el fichero, y de este modo definir el tamaño máximo que podrá ocupar en memoria, y reservar dicho espacio en la misma.

Soporte físico

El soporte físico para este tipo de ficheros es el disco duro, ya no podemos almacenar la información en cintas magnéticas, ya que estas no admiten físicamente el acceso aleatorio, y debido a su propio funcionamiento te fuerzan a un acceso secuencial.

Ejemplo de archivo de acceso aleatorio

Después de explicar como funcionan los archivos de acceso aleatorio, para entenderlo mejor, os propongo un ejemplo, un caso práctico: vamos a ayudar a Antonio a mejorar su productividad en su tienda SuperGades. El problema que tiene es que su fichero de proveedores, que es un fichero de acceso secuencial, tiene ya 1.000 registros, y cada vez que busca los datos de un proveedor tarda de media 1 minuto. Recordemos que todavía estamos en el siglo pasado y no contamos con mucha capacidad de almacenamiento ni de computación, otro gallo nos cantará cuando SuperGades halla crecido y evolucionado y estemos utilizando el Big Data.

Antonio sabe que ganaría mucho tiempo si obtuviera los datos del proveedor en no más de 5 segundos, y alguien le ha explicado que puede conseguirlo si migra todos sus datos a un archivo de acceso aleatorio.

Os propongo el siguiente ejercicio para recorrer el camino con Antonio y entender como funcionan los archivos de acceso aleatorio.

Paso 1: Fichero secuencial de partida

El fichero de proveedores de Antonio era:

Frutas Gutierrez
Antonio Gutierrez
607454545
<FIN>
Hortalizas del Sur
Guillermo Morales
652854874
<FIN>
Azucarera Sevillana
Rodrigo Mendez
622525885
<FIN>

Como este fichero ha crecido hasta 1.000 proveedores, vamos a trabajar con una versión “reducida” para hacerlo operativo.

Supongamos que ahora nuestro fichero es:

Frutas Gutierrez
Antonio Gutierrez
607454545
<FIN>
Hortalizas del Sur
Guillermo Morales
652854874
<FIN>
Azucarera Sevillana
Rodrigo Mendez
622525885
<FIN>
….
…..
…..
Huevos La Puebla
Araceli Arnedo
652879137
<FIN>
….
….
….
Arroces La Cigala
Maria Alvarez
677889922
<FIN>

Donde los puntos supensivos indican un espacio en el que habría varios registros, en total tendríamos 1.000

Paso 2: Definiendo la estructura de registro

Como habíamos visto, para poder implementar el acceso aleatorio, la longitud de los registros tenía que ser fija. Para definir la longitud de un registro, tenemos que definir las longitudes de sus campos.

Para nuestro fichero, podemos asumir que vamos a trabajar con caracteres ANSI, de esta manera cada carácter ocupará un byte.

Definimos la longitud en caracteres/ bytes de los distintos campos:

  • 1 campo: 30 bytes (nombre del proveedor)
  • 2 campo: 30 bytes (nombre del contacto en el proveedor)
  • 3 campo: 9 bytes (número de teléfono del contacto)
  • 4 campo: 0 bytes . Eliminamos la marca de fin de registro, ya que esta la usábamos realmente en un fichero de acceso secuencial para sincronismo. Ahora, con el acceso aleatorio, no vamos a usarla, sino que nos colocaremos en el inicio del registro que queramos leer, y leemos tantos caracteres como la longitud del registro, en nuestro caso, 69.

De manera visual, representándolo únicamente para el primer registro, sería algo así:

Estructura del registro
Estructura fija del registro del fichero de acceso aleatorio

Observamos que en aquellos campos en los que no estoy seguro de la longitud que tendrán los datos, los definimos con cierto margen, por lo que en la mayoría de los casos estaremos infrautilizando la memoria, reservando espacio para datos que realmente no necesitamos. No obstante hay que hacerlo de esta manera porque queremos asegurar que se pueden registrar los datos más largos que podamos tener.

Paso 3: Del fichero de acceso secuencial al fichero de acceso aleatorio

Definidas las longitudes de los campos, Antonio tendría que pasar todos los datos de proveedores a la nueva estructura de datos. Esto obviamente no se haría de forma manual, contaría para ello con un programa que realizaría esta tarea.

Paso 4: Accediendo a un registro completo

Si quisiéramos acceder al registro 777, nos colocaríamos en la posición 53.545 y leeríamos 69 bytes.

¿Cómo calculamos la dirección?. Sencillamente multiplicamos 69 bytes que ocupa cada registro por 776, lo que nos da un valor de 53.544 bytes. El registro 777 empezaría justo en el byte siguiente.

Paso 5: Comparativa aproximada de tiempos

En un fichero secuencial, para llegar al registro 777, tendríamos que leer todos los registros anteriores. Si bien, los registros serían más cortos, ya que no se reserva espacio extra en memoria que no se rellene con datos.

Supongamos que la media de la longitud del registro es de 50 bytes frente a los 69 bytes de longitud del registro del archivo de acceso aleatorio. Y que además, el tiempo de lectura de un carácter es de 1 milisegundo. Para cuando llegáramos al registro 777, habríamos leído: 50*776 = 38.800 caracteres, lo que nos hubiera llevado casi 39 segundos. Un tiempo de espera extremadamente alto.

Por el contrario, con el acceso aleatorio, sabiendo donde tenemos que posicionar el lector, es cuestión de milisegundos, es decir, prácticamente percibido por el usuario como inmediato.

Aquí es donde Antonio consigue una mejora de la productividad por la reducción considerable de los tiempos de espera.

Paso 6: Experimentando

Creamos una base de datos nueva, le ponemos el nombre que queramos, por ejemplo: BBDD2

Paso 7: Creamos un modulo nuevo

Vamos a la pestaña “HERRAMIENTAS DE BASE DE DATOS” , pulsamos en “Visual Basic”.

A continuación, en el menú Inserta/Modulo, creamos un nuevo módulo. En mi caso, lo dejo con el nombre por defecto: “Módulo1”, ya que sólo lo vamos a usar para practicar.

Paso 8: Programamos un procedimiento para crear el archivo secuencial de partida

Lo primero que haremos será crear un archivo con los datos. Crearemos los proveedores que indicaba en pasos anteriores, y rellenaremos el resto de posiciones con nombres de proveedores genéricos, al final tendremos un fichero con 1.000 registros.

El procedimiento que realizaría esta tarea sería:

Sub CrearArchivoSecuencial()

Dim i As Integer
Dim prov As String
Dim cont As String


On Error GoTo e

ChDrive ("C")
ChDir "C:\pruebas"

'Instrucción Open: https://docs.microsoft.com/es-es/office/vba/language/reference/user-interface-help/open-statement
Open "Proveedores.txt" For Output As #1

'Registro de proveedores
Print #1, "Frutas Gutierrez"
Print #1, "Antonio Gutierrez"
Print #1, "607454545"
Print #1, "<FIN>"
Print #1, "Hortalizas del Sur"
Print #1, "Guillermo Morales"
Print #1, "652854874"
Print #1, "<FIN>"
Print #1, "Azucarera Sevillana"
Print #1, "Rodrigo Mendez"
Print #1, "622525885"
Print #1, "<FIN>"

For i = 4 To 766
prov = "Provedor nº" & i
cont = "Contacto de Proveedor nº" & i
Print #1, prov
Print #1, cont
Print #1, "xxxxxxxxx"
Print #1, "<FIN>"
Next

Print #1, "Huevos La Puebla"
Print #1, "Araceli Arnedo"
Print #1, "652879137"
Print #1, "<FIN>"

For i = 778 To 1000
prov = "Provedor nº" & i
cont = "Contacto de Proveedor nº" & i
Print #1, prov
Print #1, cont
Print #1, "xxxxxxxxx"
Print #1, "<FIN>"
Next

'Cerrar el archivo:
Close #1
MsgBox ("Guardados 1000 registros de proveedores")
Exit Sub
e:
MsgBox (Err.Description)
End Sub

Paso 9: Transformamos el fichero de proveedores a la nueva estructura fija

Teniendo en cuenta la estructura del fichero aleatorio que hemos definido en el paso 2. Tenemos que recorrer el fichero de proveedores y extender los datos en los distintos campos para que ocupen la longitud fijada en la nueva estructura. Para hacerlo visible rellenare los espacios añadidos con un punto “.” .

Para ello usaremos el siguiente procedimiento:

Sub PasarSecuencial_Aleatorio()

ChDrive ("C")
ChDir "C:\pruebas"

Dim linea As String
Dim escribir As String
Dim MyChar As String
Dim tipoRegistro As Integer
Dim i As Integer
Dim j As Integer

Open "Proveedores.txt" For Input As #1
Open "ProvAccesoAleatorio.txt" For Output As #2

linea = ""
tipoRegistro = 1

Do While Not EOF(1)
    MyChar = Input(1, #1)
    If MyChar = Chr(13) Then
        If tipoRegistro = 4 Then
            tipoRegistro = 1
            linea = ""
        Else
            Select Case (tipoRegistro)
                Case 1
                    escribir = linea
                    j = Len(linea)
                    For i = j To 30
                        escribir = escribir & "."
                    Next i
                    Debug.Print escribir
                    Print #2, escribir
                    linea = ""
                Case 2
                    escribir = linea
                    j = Len(linea)
                    For i = j To 30
                        escribir = escribir & "."
                    Next i
                    Debug.Print escribir
                    Print #2, escribir
                    linea = ""
                Case 3
                    escribir = linea
                    j = Len(linea)
                    For i = j To 9
                        escribir = escribir & "."
                    Next i
                    Debug.Print escribir
                    Print #2, escribir
                    linea = ""
            End Select
            tipoRegistro = tipoRegistro + 1
        End If
    ElseIf (MyChar <> Chr(10)) Then
        linea = linea + MyChar
    Else
    End If

Loop


Close #1
Close #2

End Sub

Paso 10: Reduciendo el tamaño del fichero

Para trabajar con el fichero en la práctica, vamos a reducir el número de proveedores a 20. El objetivo es poder trabajar con variables enteras, sin tener que irnos a manejar grandes números, y no tener problemas de desbordamiento.

Paso 11: Desplazándonos directamente a un número de registro

Tenemos que primero calcular la posición en la que empezaría el registro, y a continuación movernos hasta ella y leer una cantidad determinada de datos. Todo sometido a una estricta estructura.

Para realizarlo, usamos el siguiente procedimiento:

Sub IrRegistro()


ChDrive ("C")
ChDir "C:\pruebas"

Dim NumeroRegistro As Integer
Dim posicion As Integer
Dim contador As Integer
Dim MyChar As String
Dim i As Integer
Dim texto As String


Open "ProvAccesoAleatorio.txt" For Input As #1

NumeroRegistro = CInt(InputBox("Introduce numero de registro. Asegurate que este entre 1 y 1000", "Buscar registro por su número"))
posicion = (30 + 30 + 10 + 8) * (NumeroRegistro - 1)
posicion = posicion + 1
contador = 0
texto = ""

Do While Not EOF(1)
    MyChar = Input(1, #1)
    'Debug.Print contador
    'Debug.Print posicion
    contador = contador + 1
    If posicion = contador Then
    For i = posicion To (posicion + 75)
        texto = texto + MyChar
        'Debug.Print MyChar
        MyChar = Input(1, #1)
    Next i
    Debug.Print texto
    Exit Do
    End If
Loop

Close #1
End Sub

NOTA:

Este post es parte de la colección “Sistemas de acceso y almacenamiento de datos”. Puedes ver el índice de esta colección aquí.