Ya vamos al tema de esta
entrega... la número doce, (duodécima), es que es un lió esto
de los números ordinales, así que usaré números normalitos,
que todos los entendemos mejor...
Con esta entrega, empiezo la
serie de manejo de datos almacenados en disco. Así que presta
atención a esta y las siguientes entregas, para que esto del
manejo de la información almacenada en disco te sea fácil de
usar.
Además de las bases de datos,
que también veremos en este curso básico... o en las secuelas
que pueda tener... existe una forma de almacenar los datos que
nuestra aplicación pueda manejar. Porque de qué serviría hacer,
por ejemplo, un programa tipo editor de textos si no pudiésemos
almacenar lo que se ha escrito...
No, aún no te voy a explicar cómo hacer un editor de textos,
antes hay que ver algunas cosillas más, pero todo llega en esta
vida, así que no desesperes...
El Basic maneja tres tipos de
ficheros: secuenciales, aleatorios y binarios.
Cada uno tiene una serie de
características en la forma de acceder a los datos.
El más básico y también el más empleado, es el secuencial; con
este tipo de fichero, los datos se almacenan y recuperan de forma
secuencial, es decir: un dato después de otro...
El inconveniente que tiene esta forma de almacenar los datos, es
que para recuperar lo que esté en la décima posición, tenemos
que leer los nueve anteriores...
Si tenemos que guardar, por
ejemplo, el contenido de un array de strings, lo normal es que lo
hagamos secuencialmente, es decir primero el contenido de la
primera variable del array, después la segunda, tercera, etc.,
hasta llegar a la última.
Para recuperar estos datos, actuaríamos de igual forma, pero
asignando al array los datos leídos del disco. Recuerda que para
asignar una posición N, antes tendremos que leer las N-1
posiciones anteriores.
La ventaja de esta forma de almacenar los datos, es que la
longitud de las cadenas, por ejemplo pueden ser variables... esto,
ahora te parecerá una cosa normal, pero lo entenderás cuando
veamos los otros tipos de accesos.
También permite que puedas almacenar distintos tipos de datos...
no te preocupes, ya sabes que en estas entregas todo está
"demostrado"... más o menos, ya que la teoría está
bien para los teóricos, pero para los torpes como yo... lo mejor
es la práctica... no es que quiera llamarte torpe... pero, así
me siento menos solo... jé, jé.
El inconveniente es, como ya he
repetido, que para acceder a un dato en concreto, se deben
"leer" todos los anteriores.
Esta inconveniencia del acceso secuencial se arregla usando el
acceso aleatorio. Con este tipo de acceso, puedes leer del fichero
el dato almacenado en cualquier posición, sin tener que leer
primero todos los anteriores... Pero, no todo es perfecto...
también tiene un "pequeño" inconveniente... que los
datos guardados en un fichero aleatorio deben ocupar el mismo
espacio, o sea que sean de la misma longitud... Si guardas cadenas
de caracteres, todas ocuparán el mismo espacio en el disco,
aunque unas tengan más caracteres "válidos" que
otras... También se pueden mezclar números y cadenas de
caracteres... pero eso tiene también sus
"inconvenientes" o mejor dicho su "truco" para
poder usarlo sin armar un KAOS...
Ya que estamos con los distintos tipos de acceso, te diré así
por encima de que va el tipo Binario, éste es un poco especial y
permite leer la información almacenada de la forma que queramos,
todo dependerá de la longitud de la variable que usemos para
acceder al fichero... todo estas cosas quedarán explicadas y
aclaradas en esta o en próximas entregas...
Bien, ya sabes que tipos de
ficheros puedes manejar con el Visual Basic, ahora vamos a ver
como hacerlo, por supuesto, con las instrucciones correspondientes
para poder hacerlo, ya que de eso se trata... o es que ¿esperabas
poder acceder a la información de los ficheros sin usar
instrucciones del VB?
Cada vez que quieras abrir un
fichero, tienes que usar un número de "canal" por el
que VB nos suministrará la información, este canal. El canal se
indica por medio de un número de 1 a 255. Gracias a este número,
el Basic se comunica con el sistema operativo para acceder a los
datos. El Basic nos facilita la tarea de conseguir ese número,
con idea de que no usemos una línea que esté en uso... La
instrucción, en realidad es una función, para conseguir un
número de canal libre, es: Freefile. Esta
función devuelve un número entero, el cual se almacenará en una
variable y así podremos usarlo para el manejo de los datos
almacenados.
NumFic = Freefile
Una vez que conozcamos un canal
por el que poder acceder, tendremos que abrirlo:
Open "Prueba.txt" For Output As
NumFic
Con esta línea, abrimos el fichero Prueba.txt de forma secuencial
para poder escribir en él.
Una vez que tenemos una "vía" de comunicación,
podremos escribir información usando una versión un poco
maquillada de la instrucción Print... El maquillaje es el número
de canal con el que podemos acceder al fichero:
Print #NumFic, "Lo que sea"
#NumFic es el número de fichero (o canal) por el
que accedemos al fichero abierto y después de ese número, usamos
una coma y a continuación lo que queremos guardar en el fichero.
Cuando hayamos acabado de guardar cosas, tendremos que cerrar el
fichero que hemos abierto, para poder liberar ese canal abierto y
así poder usarlo en otra ocasión, esto se consigue con el
comando Close:
Close NumFic
Es importante esto de cerrar el
fichero abierto, ya que en ese momento es cuando el Basic guarda
la información que aún tiene "temporalmente"
almacenada en una memoria intermedia que usa para que el acceso a
datos sea, al menos en teoría, más rápido. A esta memoria
intermedia se le llama "buffer". El VB la usa para ir
guardando la información que vamos a grabar físicamente en el
disco, antes de grabarla, la guarda ahí y cuando está llena, la
escribe en el disco y la libera, esto se consigue con el close,
para asegurarnos que todo lo que tenga que estar guardado,
realmente lo esté. El valor de este búfer para los ficheros
secuenciales y aleatorios puede ser de 32767 bytes como máximo,
antes con el Basic del DOS el valor por defecto era de 128 bytes y
el máximo de 255 caracteres, pero esto hace tiempo que cambió y
ahora incluso, (al menos en el acceso de 32 bits), aunque en la
ayuda no lo indique así, puede ser mayor que todo eso... Ya
tendremos ocasión de comprobarlo.
Todo esto está muy bien, pero si
quieres especificar esa longitud... ¿cómo y/o dónde se
especifica?
Ahora sabrás cómo y dónde. Para ello vamos a ver cómo se usa
al completo la orden OPEN y sus posibilidades de uso.
Open
RutaAcceso [For Modo]
[Access acceso] [tipo
de bloqueo] As
[#]númerofichero [Len=longitudregistro]
Lo que está entre corchetes son
parámetros opcionales.
Fíjate en el detalle que FOR Modo está entre corchetes, esto
significa que si no se especifica el modo, el Visual Basic
entiende que quieres acceder de forma aleatoria. La explicación
de cada uno de estos parámetros los tienes en la ayuda, así que
si no quieres esperar a que los explique todos, vete a la ayuda y
le echas un vistazo.
Yo empezaré a explicarte lo que ahora necesitas saber y poco a
poco iremos viendo las distintas posibilidades... Pero si no
quieres esperar... ya sabes... echa mano del F1 y accede a la
explicación de la ayuda o del manual...
Vamos a ver lo que nos interesa
de esta instrucción:
| RutaAcceso |
|
El
path completo, o a medias, de dónde queremos que se
almacene el fichero o el lugar en el que está almacenado.
Por ejemplo: C:\Datos\Un directorio\Prueba.txt
.\Algo\Prueba.txt, siempre que en el
directorio actual haya un directorio que se llame
"Algo"
o simplemente Prueba.txt (esto le
indicará que estará en el directorio actual) |
| Modo |
|
- Output,
para ficheros de salida, es decir para guardar los
datos.
Si el fichero existe, lo borrará (sobrescribirá) y
si no existe, lo creará.
- Input,
para leer los datos de un fichero ya existente.
Append, como el Output, pero
añadiendo la información al final del fichero, si
este ya existe.
- Random,
para acceso aleatorio.
- Binary,
para acceso binario.
|
| As
NúmeroFichero |
|
Aquí
se indica el número de fichero (canal) por el que
accederemos a la información.
El signo de número (#) es opcional. Y NúmeroFichero,
puede ser una variable o una constante. |
Las otras opciones ya las
veremos, ahora nos centraremos en las cosas que son más fáciles,
siempre hay tiempo para complicarse la vida, así que nos la
complicaremos más adelante, cuando ya tengamos un poco de idea de
todo este follón...
RutaAcceso, a estas alturas
deberías saber de que va todo esto del PATH, pero si no lo sabes,
te lo explico por encima: un path es una ruta de acceso a un
fichero... ¿comor? Pues eso, si quieres guardar la información
en el disco, tendrás que saber en que parte del disco la quieres
guardar, incluso en que disco quieres almacenarla. Y lo más
importante, cómo vas a llamar el sitio en el que se guardará.
Esto es un poco como las variables, si quieres tener distintas
cosas en la memoria del Basic, usas distintos nombres de
variables, pues lo mismo con los ficheros, usando distintos
nombres de ficheros puedes tener información diferente almacenada
en el disco.
Para empezar, debes saber que tienes que usar un nombre en el que
almacenar la información que quieres "conservar", para
después poder acceder a ella en el momento que la necesites.
La ventaja de esto con respecto a los nombres de las variables es
que puedes usar distintas partes del disco para guardar esa
información, aunque el nombre "real" del fichero sea el
mismo...
A ver, si quieres guardar los rascones esos que te dabas en las
entregas anteriores, puedes decirle al Basic que quieres usar un
fichero que se llame: rascones. Pero suponte que
quieres tener todos los rascones de todos los meses del año
almacenados en distintos ficheros, uno para cada mes. Podrías
hacer algo como esto: darle a cada fichero un nombre diferente o
bien usar la "extensión" del fichero para cada uno de
los meses...
Por ejemplo: rascones.ene para enero, rascones.dic
para los de diciembre... etc.
Y si quieres que esos datos se guarden en el disco A, pues sólo
tienes que decirle que el fichero se llama: A:\rascones.ene
Si tienes la intención de guardar cada grupo de ficheros en
carpetas (directorios) diferentes, también puedes indicarselo en
la ruta esta de acceso: C:\Datos\A1998\rascones.ene
Por supuesto para poder hacer esto último debes tener un disco C
(¿quién no lo tiene?), un directorio A1998 que está dentro de
otro llamado Datos que está a su vez en el directorio raíz del
mencionado disco C.
En caso que no se especifique la ruta completa, el Visual Basic
usará el directorio actual para acceder al fichero.
Debes saber que el visual creará
el fichero indicado, pero si no existen los directorios o no puede
tener acceso a ellos, dará error y no abrirá el fichero. ¿Que
error? El número 76: Path not found (No se ha encontrado la ruta
de acceso)
Hay más errores, muchos, pero estos ya te los irás encontrando y
en su momento veremos cómo poder detectarlos.
Veremos también cómo crear las
rutas esas de acceso, en caso de que no existan, para así
asegurarnos que existen antes de guardar la información en el
disco... pero todo a su debido tiempo...
Ahora lo que vamos a ver es unos
ejemplos de cómo guardar información y después poder
"leerla", ya que esto es lo más básico y lo que en
principio debemos saber.
¿Cómo guardar la
información?
Ya te he dicho antes de que con Print se puede guardar la
información en el disco, veamos cómo:
Print #NumFic, Nombre
Print #NumFic, 125
También podemos guardar esta
misma información así:
Print #NumFic, Nombre, 125
Es decir que si quieremos guardar
varias cosas con una misma instrucción, lo haremos usando una
coma como separador. De esta forma cada cosa que esté separada se
guardará en el disco en "líneas" distintas.
¿Cómo leer la
información?
Para poder leer la información, además de abrir el archivo para
lectura modo INPUT, hay que usar una de estas instrucciones:
Input #NumFic, Variable
También con: Line Input #NumFic, variable.
La diferencia entre el Input
y el Line Input la veremos dentro de un ratillo.
Antes tendremos que ver cómo acceder a ese nombre y a ese número
que antes hemos guardado...
Input #NuFic, unNombre, unNumero
Un detalle que debes tener en
cuenta es que si el Nombre que guardamos tiene alguna coma, puede
que no accedas a los datos como pretendías... Vamos a verlo con
un ejemplo. Crea un nuevo proyecto en el VB y añade dos botones
(CommandButton), escribe este código y pruebas:
Private Sub Command1_Click()
Dim Nombre$, Num%
Dim NumFic%
Nombre = "Pérez, Pepito"
Num = 22
NumFic = FreeFile
Open "C:\Prueba.txt" For Output As NumFic
Print #NumFic, Nombre, Num
Close NumFic
End Sub
Private Sub Command2_Click()
Dim Cadena$, Numero%
Dim nF%
nF = FreeFile
Open "C:\Prueba.txt" For Input As nF
Input #nF, Cadena, Numero
Close nF
MsgBox "Cadena= " & Cadena & vbCrLf & _
"Número= " & Numero
End Sub
Ahora pulsa en F5 y dale primero
al botón Command1, después le das al Command2 y verás que no te
muestra lo esperado.
En lugar de mostrar:
Cadena= Pérez, Pepito
Número= 22
Te ha mostrado:
Cadena= Pérez
Número= 0
¿Que ha ocurrido?
En primer lugar, decirte que esto mismo con el Basic del MS-DOS
hubiese dado un error, pero debido a como maneja el VB las
variables, se ha tragado lo que ha encontrado... ¿Que ha
encontrado? Pues que tiene que asignar a Cadena
la "palabra" Pérez y a la variable Numero
el "número" Pepito... que al no ser un número, le ha
dado el valor cero...
Esto es debido a que cuando INPUT
lee los datos espera una coma o el final de línea para
"distinguir" entre los diferentes datos a asignar a las
variables indicadas.
Vale, dirás, pongámoslo en distintas líneas y así los leerá
correctamente:
Input
#nF, Cadena
Input #nF, Numero
Pero con esto no lo
solucionarás, pruébalo y verás que tengo razón.
¡De gente desconfiada está el mundo lleno! ...no te he dicho que
daría el mismo resultado... HUM!
Bien, ¿cómo solucionarlo?
¿Lo has adivinado? Pues eso mismo, usando el Line Input... Pero
con Line Input no se pueden especificar más de una variable en la
misma instrucción... así que ponlas en dos líneas.
Line
Input #nF, Cadena
Line Input #nF, Numero
¡OPS! ¿Que ha
ocurrido?
Si has pulsado simplemente F5, te habrá dado un error al pulsar
en el segundo botón... Y si has pulsado Control+F5, te habrá
indicado, con el mismo error, que los tipos no coinciden, (si usas
la versión inglesa: Type Mismatch)
Esto es debido a que Line Input
sólo puede leer cadenas de caracteres, mejor dicho sólo se
pueden usar variables de tipo string (cadena), ya que esta
instrucción lee todo lo que hay en la línea actual del fichero
abierto, hasta el final de la línea.
¿Cómo solucionarlo?
Usando una variable intermedia o simplemente usando el INPUT
normal para leer el número.
Veamos cómo sería de las dos formas:
Line
Input #nF, Cadena
Input #nF, Numero
Dim
sTmp$
Line Input #nF, Cadena
Line Input #nF, sTmp
Numero = Val(sTmp)
Ahora si que tendremos el
resultado correcto:
Cadena= Pérez, Pepito
Número= 22
¡EXACTO!
Tampoco nos ha mostrado esto...
¿Por qué?
Muy sencillo, realmente no es sencillo, sino que después de que
me haya ocurrido como dos millones de veces, resulta hasta
lógico... 8-(
Si miras el contenido del fichero C:\Prueba.txt, te darás cuenta
de que el contenido de este fichero es:
Pérez, Pepito 22
Entre Pepito y el 22 hay un tabulador, Chr$(9). Esto es debido a
que Print x, y muestra los valores en distintas
"posiciones" de tabulación, lo mismo ocurre cuando se
guarda en el disco...
Para solucionar todo esto y hacer que la cosa funcione bien, te
aconsejo que cada dato lo guardes con distintas instrucciones
Print, de esta forma cada dato se guarda en distintas líneas del
fichero.
Así que cambia el código del Command1, para que en lugar de un
sólo Print, haya dos:
Print #NumFic, Nombre
Print #NumFic, Num
Ahora todo debe funcionar bien.
Vale, pruébalo si no te fías...
¿Tenía yo razón? Pues claro, ...ya que lo he comprobado
antes... ;-)
Si no sabemos el tipo de datos
que tenemos almacenado, lo mejor es usar la instrucción Line
Input y así nos curamos en salud, pero si sabemos que, por
ejemplo, todos los datos son numéricos y se han almacenado sin
usar comas...
Mejor un ejemplo:
En este caso vamos a guardar en un array una serie de números
aleatorios, los vamos a guardar en un fichero y después los
leeremos para asignarlos en otro array y los mostraremos en un
label.
Para hacerlo, crea un nuevo
proyecto, el anterior lo puedes borrar ya que es de una inutilidad
total.
Añade un Label que ocupe prácticamente todo el Form, salvo la
parte de abajo, en la que pondrás dos botones.
Pega el código este que te pongo, pulsa F5 y primero pulsa en el
Command1, para después pulsar en el Command2
Private Sub Command1_Click()
Dim Numeros(1 To 10) As Integer
Dim i%
Dim nFic%
Randomize
'Asignamos los valores
For i = 1 To 10
Numeros(i) = Int(Rnd * 100) + 1
Next
'Abrimos el fichero
nFic = FreeFile
Open "C:\Prueba.txt" For Output As nFic
For i = 1 To 10
Print #nFic, Numeros(i)
Next
Close nFic
Label1 = "Números guardados en el disco"
End Sub
Private Sub Command2_Click()
Dim MasNumeros(1 To 10) As Integer
Dim i%
Dim nFic%
'Abrimos el fichero para leer los datos
nFic = FreeFile
Open "C:\Prueba.txt" For Input As nFic
For i = 1 To 10
Input #nFic, MasNumeros(i)
Next
Close nFic
'Asignamos estos números al label:
Label1 = ""
For i = 1 To 10
Label1 = Label1 & MasNumeros(i) & vbCrLf
Next
End Sub
Este es un ejemplo sencillo de
cómo asignar datos a un array, guardarlos en el disco y después
leerlos.
Y hasta aquí hemos llegado...
Como ejercicio,
haz un programa que al pulsar en un botón, te pida diez nombres,
los guarde en un fichero y después pulsando en otro botón los
muestre en un label.
No es necesario que uses un array para guardar los datos, pero
podrías hacer dos versiones, con y sin un array.
Como pista te recordaré que la
función InputBox puede servirte para esto de
preguntar, ya que el valor que devuelve es la cadena de caracteres
introducida en la caja de diálogo que muestra.
Esto del InputBox ya lo vimos en la novena entrega, o en las
soluciones, pero te explico brevemente cómo funciona:
variable$=InputBox("Escribe un nombre")
¿Facil, verdad? Pues esa es toda la pista que te voy a dar.
Ahora se "legal" y no
veas las
soluciones de esta entrega
hasta que lo hayas hecho tú.
En la página de las soluciones
tienes un "extra", así que aunque sepas cómo
hacerlo... te pasas a verla... ¿vale?
Espero que te haya resultado
instructiva esta entrega, a pesar de haberte dejado con la miel en
la boca, pero así son las cosas y no es plan de darlo todo de
golpe.
¿Para cuando la siguiente entrega? ¡Ah!, misterios de la vida...
eso ni se sabe. Así que permanece a la escucha y ya verás
cuando... no quiero prometer que será pronto, que después me
regañas... así, que... ¡a esperar!
Si hay algo que no entiendas o
simplemente quieres hacer algún comentario sobre esta entrega o
cualquier otro tipo de peloteo o lo que te de la gana decirme
sobre el curso básico, usa
este link...
Pero no lo aproveches para las consultas... ¡que te conozco
rosco!
Nos vemos pronto.