Professional Documents
Culture Documents
6
FICHEROS EN VISUAL BASIC
- Secuenciales
- Aleatorios (Random)
- Binarios
FICHEROS SECUENCIALES
Este tipo de ficheros nos permite guardar información de cualquier longitud. En este tipo de
ficheros, la información se guarda colocando un carácter tras otro. La forma de leerlos es,
igualmente, carácter tras carácter. (Byte tras byte). Son los mas sencillos de manejar, y los
utilizados para guardar texto en ASCII. Permiten guardar datos en un fichero con un determinado
nombre, "machacando" la información de otro posible fichero que ya estuviese en el disco con el
mismo nombre, o añadir la información nueva a continuación de la ya existente.
Para abrir un fichero secuencial para guardar información, debemos ejecutar la siguiente
instrucción:
Numerocanal debe ser un número comprendido entre 1 y 255. Representa el número del canal
por donde introduciremos los datos. Normalmente se llama también número de archivo. No
puede haber mas de un archivo abierto con un número de canal determinado.
Close # Numerocanal
Si no se especifica Numerocanal (la instrucción Close a secas) se cerrarán todos los ficheros
abiertos actualmente.
Para introducir la información, pueden emplearse dos métodos: Print y Write Nos centraremos
de momento solamente en Print.
Print
Introduce la información de forma secuencial, byte tras byte tal como se comentó.
Sirve para guardar textos. Por ejemplo si deseamos guardar en ese fichero el
contenido de una caja de texto llamada Text1, basta con ejecutar la siguiente
instrucción:
El texto queda en el fichero en caracteres ASCII, que se pueden leer con el Bloc
de Notas.
Cuando los datos se han introducido con la instrucción Print, la forma de acceder a ese texto es
muy sencilla:
Se utiliza la instrucción Input o Line Input para sacar los datos del fichero.
Por ejemplo, VariableString = Input (1, #1) extrae un carácter del fichero abierto como #1. El
número máximo de caracteres a extraer de un golpe mediante la instrucción Input está limitado a
65.534.
Verá un poco mas adelante la propiedad LOF de los ficheros secuenciales. LOF devuelve un valor
igual a la longitud total del fichero. Si ejecutamos la instrucción :
Para no emplear una palabra tan larga como Numerodecanal, utilizaremos de ahora en adelante
el número 1 como número de canal. Recuerde que ese número puede ser un número
comprendido entre el 1 y el 255
leeremos el fichero de una única vez. Este procedimiento puede ahorrarle cierto tiempo a la hora
de la lectura. (Por lo dicho anteriormente, este procedimiento de leer todo el fichero de un golpe
solamente se podrá hacer si la longitud del fichero (LOF(1)) es inferior a 65.534 bytes. Tenga esto
presente cuando vaya a leer un fichero que no sabe que longitud tiene. Para curarse en salud, le
recomiendo que lea los ficheros secuenciales carácter a carácter. Input(1,#X) pues tarda poco
mas que leyéndolo de un golpe. Claro que para leer un fichero carácter a carácter debe poner un
bucle en el que se van leyendo los caracteres hasta que llaga al final del fichero..
Dim A As String A es la variable donde meteremos el carácter que extraemos del fichero.
Dim MiVariable as String MiVariable es una variable tipo string donde vamos a meter todo
el contenido del fichero
Do Until EOF(1) El programa ejecutará este bucle hasta que se cumpla que
EOF(1) sea True. EOF(NumerodeCanal) es una propiedad de los
ficheros cuando están abiertos, que es True cuando la posición del
puntero de lectura apunta al carácter Fin De Fichero (End Of File)
que es el carácter siguiente al último carácter de texto de ese fichero.
A = Input (1, #1) Estrae un carácter del fichero abierto por el canal número 1. Al
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 2
leer este carácter, el puntero de lectura avanza automáticamente
tantos caracteres como haya leído, colocándose sobre el primer carácter no
leído.
MiVariable = MiVariable & A Con esta línea vamos anexando el carácter leído a la variable
MiVariable. En vez de utilizar una variable, podríamos poner ese
texto sobre un TextoBox o un RichTextBox (RTB) (Lo verá
proximamente). Si lo ponemos en un RTB esta línea sería:
RTB.SelText = A
Sólo se utilizará la instrucción Input con archivos abiertos en modo Input o Binary. (Los Binary
Se verán a continuación) A diferencia de la instrucción Input #, (la veremos a continuación, pues
es la instrucción que deberá utilizar para leer archivos escritos con la instrucción Write ), Input
devuelve todos los caracteres que lee, incluyendo puntos y coma, retornos de carro, avances de
línea, comillas y espacios iniciales.
Existe una instrucción, Input$ , que asume que el dato a leer es un String. (Cadena de
caracteres). Puede ahorrar un poco de memoria usando esta instrucción en lugar de Input.
Nota Se proporciona otra función (InputB) para su uso con datos de byte incluidos en archivos de
texto. En lugar de especificar el número de caracteres a devolver, número especifica el número de
bytes.
La instrucción Line Input se utiliza para extraer una línea completa. Tiene la siguiente
sintaxis:
Mediante esta instrucción se extrae una línea completa (los caracteres delimitados entre dos
retornos de carro), y se le asigna esa cadena a VariableString
Una línea es un trozo de texto delimitado por los caracteres 13 (Retorno de carro) y 10 (Avance de
línea) La instrucción Line Input # lee un carácter cada vez en un archivo hasta que encuentra un
retorno de carro (Chr(13)) o una secuencia retorno de carro - avance de línea (Chr(13) + Chr(10)).
Las secuencias de retorno de carro - avance de línea no se tienen en cuenta y no se añaden a la
cadena de caracteres extraída mediante esta instrucción. Cuando lea un archivo mediante Line
Input # y lo quiere presentar en un TextBox o en el Printer, deberá introducirlos para evitar que le
salga todo el texto en una única línea.
Con lo que se ha explicado, ya puede realizar un pequeño edito de textos. Este sencillo editor
tiene un TextBox llamado TBTexto, donde podemos escribir el texto que queramos (con la
propiedad MultiLine = True y ScrollBars = Vertical), tres botones llamados BAbrir (1), (2 a y b) y
(3), para abrir el fichero y poner su contenido en TBTexto, y dos BGuardar para guardar, uno
abriendo el fichero For Append y el otro abriéndolo For Output. En este último, al guardar el texto
borramos el contenido que del fichero, si ya existiera. En el primero, lo anexamos al final del
mismo . Para conocer el nombre del fichero, ponemos un CommonDialog llamado CD1, con un
filtro CD1.Filter = “Ficheros de Texto |*.txt”
Cuando el fichero es mayor de 64 kilobytes, el leerlo de un golpe puede dar problemas. Mejor
dicho, no funciona. Deberemos leerlo en ese caso, carácter a carácter o línea a línea.
INSTRUCCIÓN WRITE
La otra forma de introducir datos en un fichero secuencial es Write. Mediante esta instrucción, no
se puede introducir texto, sino datos, aunque esos datos sean de texto. Mediante la instrucción
Write puede crear una pequeña base de datos. Eso sí, una base de datos de escasa calidad. Pero
no es momento de cuestionar la calidad de esta base de datos, sino de explicarla.
Write
Puede introducir varias informaciones, que posteriormente se podrán leer de forma
separada con la instrucción Input #. Esta forma de introducir datos en un fichero
secuencial permite realizar un fichero con distintos datos que se pueden leer en el
propio fichero, puesto que se guardan en ASCII, y leerlos mediante el programa de
una forma muy sencilla. Hacemos, en realidad, una pequeña base de datos. (Verá
a lo largo de su vida profesional que lo de pequeña no es cierto, pues es la forma
mas sencilla de guardar datos cuando la cantidad de estos datos no es muy
grande)
Lo que estamos haciendo en realidad al escribir datos mediante la instrucción Write es escribir
estos datos en un fichero secuencial, utilizando una coma como separador entre los distintos
datos. Un fichero secuencial con datos introducidos mediante la instrucción Write tendrá esta
forma :
Observe que el contenido de este fichero se diferencia algo de una simple sucesión de caracteres.
Tiene varias partes separadas por una coma. Cada una de ellas es un dato.
Imaginemos una aplicación, con la que introducimos datos de libros. La aplicación es un único
formulario donde podemos introducir la información mediante varios TextBox. Existe un Botón de
comando con el siguiente código:
Si introduce los datos del ejemplo anterior, se creará un fichero que tiene esta apariencia:
Si realizamos otra introducción de datos, con la segunda línea del ejemplo anterior, los datos
existentes en ese fichero no se borrarán, dado que lo hemos abierto con Append. Quedará de la
siguiente forma:
¿Que pasaría si leemos este fichero con la instrucción Input o Line Input # vista anteriormente ?
Pues simplemente que lo leeríamos tal como está, con sus comas y comillas dobles. No sería la
forma mas adecuada, ya que lo que queremos es obtener sucesivos datos de autores, títulos,
editoriales, precios y existencias.
Para sacar estos datos debemos leerlos con la instrucción Input #. Esta instrucción saca los datos
que hemos metido, es decir, elimina las comillas y la coma que servían de separadores.
En nuestro ejemplo, podríamos hacerlo de esta forma, aprovechando los mismos TextBox:
'Abrimos el fichero
LIBRETBTITULO.Text = TIT
LIBRETBAUTOR.Text = AUT
LIBRETBEDITORIAL.Text = NED
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 6
LIBRETBPREC.Text = PRE
LIBRETBEX.Text = EXS
' Refrescamos los TextBox
Refresh
Loop
Close #1
End Sub
Observe que los nombre de las variables en el proceso de lectura tienen distintos nombres a los
utilizados durante la escritura. Como en el fichero no se guarda ninguna referencia al respecto, lo
único que importa es que el número de variables para la lectura sea igual al número de variables
que se utilizó para la escritura, y que el orden de las variables sea correcto. Si por ejemplo, el
número de variables usadas en la introducción de datos fuese distinto al número de variables
usado en la lectura, Visual Basic nos daría un error.
Observe también que se ha introducido un temporizador. Sirve para ver los sucesivos títulos que
tenemos en nuestra base de datos tan sui generis. Se ha pretendido presentar unos datos de esta
pequeña base de datos sin complicarnos mucho la vida. Mas adelante veremos como presentarlos
de una forma correcta. Este tipo de ficheros no es el mas adecuado para construir bases de datos,
es complicado manejar ficheros de mas de unas pocas líneas, por lo que para tener muchos datos,
este tipo de ficheros no es recomendable. No es aconsejable ni para muchos datos ni para pocos
datos. Pero es obligación del autor explicarlo … y de advertirlo.
En esta pequeña aplicación mostrábamos las informaciones sucesivamente según las íbamos
leyendo del fichero. Interrumpíamos momentáneamente la lectura para presentar cada
información durante un instante, ya que como tenemos cinco datos distintos en cada registro y
cinco TextBox para presentarlos, deberemos presentar una información tras otra. Esto no parece
en principio una solución práctica para una base de datos, donde lo que interesa es disponer de
todos los datos para usarlos cuando sea necesario. Esto nos lleva a crear una matriz para albergar
todos los datos de la base, ya que los ficheros secuenciales se leen y se les tiene que extraer toda
la información de un golpe, ya que no permiten ir a leer hacia atrás. Por lo tanto, si deseamos
disponer de todos los datos, deberemos guardarlos en la memoria, en una matriz. Imagínese que
estamos tratando datos de varios miles de libros en el ejemplo anterior. Si la información de cada
campo es medianamente extensa, no tendríamos memoria RAM suficiente en el ordenador para
albergarlos. Esto nos lleva a pensar en otro tipo de archivo que veremos a continuación, los
Random (aleatorios), que permiten leer solamente los registros que nos interesan.
Pero volvamos a nuestra aplicación de librería, donde hemos hecho una variación, los campos
PRECIO y EXISTENCIAS los vamos a tratar ahora como números (Integer). También se ha
introducido otro campo tipo texto, para introducir la edición. El fichero creado tras introducir varios
libros quedó de la siguiente forma :
Observe que los dos últimos campos (correspondientes a PRECIO y EXISTENCIAS) no están
entre comillas, pues no se trata de texto, sino de números.
(Observe también la gran ventaja de tener una base de datos con datos completamente legibles)
Se han introducido alguna variaciones en el programa. Entre ellas, se crea una matriz de variables
de 5 x n (n=número de registros). También se le añaden unos botones para poder recorre toda la
base de datos.
El programa necesita que le introduzcamos el nombre del fichero que alberga la base de datos.
Por sencillez no se ha usado ningún CommonDialog y se introduce directamente el nombre de
este fichero en un TextBox llamado TBNombreFichero
Donde las variables TITULO, AUTOR, EDITORIAL y EDICION serán del tipo String y PRECIO y
EXISTENCIAS serán de tipo numérico. Podemos saberlo, ya que en una línea cualquiera del
fichero anterior :
Pero existe otra forma mejor (al menos un poco mas complicada) para leer estos datos, y evitar el
problema que teníamos antes de tener que hacer un temporizador para poder ver, aunque solo sea
un momento, los datos. Podemos meter los datos a una matriz que tenga tantas columnas como
datos (campos) (en el ejemplo 6, cuatro String y dos numéricos), y tantas filas como apuntes
(registros) tengamos.
Para ello, antes de nada debemos definir un tipo de variable, mediante la instrucción Type. Parece
que no nos basta con los tipos de variable que trae VB (Long, String, Integer ...) y es cierto. La
variable que necesitamos no es de ningún tipo de esos. Está compuesta por varias secciones, y
cada una de ellas puede ser de un tipo distinto. Este tipo de definiciones debe hacerse en un
módulo (Véase instrucción Type en la ayuda de VB), por lo que se ha creado un módulo llamado
LIBREMD2.BAS, con el siguiente código :
Type REGISTROLIBRO
AUTOR As String
TITULO As String
EDITORIAL As String
EDICION As String
PRECIO As Integer
EXISTENCIAS As Integer
End Type
Esto es lo que se llama DEFINIR una variable. Es como hacerse un traje a medida. Y dese cuenta
de que es un tipo de variable (REGISTROLIBRO) formado por varias partes (AUTOR, TITULO,
Etc.) Observe que DEFINIR una variable NO es lo mismo que DECLARAR
En el apartado de Declaraciones del General del formulario declaramos las variables, entre ellas
una variable, REGISTROLIBROS, de la cual decimos que va a ser una matriz mediante los
paréntesis que la acompañan, y además declaramos que va a se similar a REGISTROLIBRO ya
definida en el módulo.
Dim NR As Integer
Dim REGISTROLIBROS() As REGISTROLIBRO
Dim NRP As Integer
En el ejemplo preparado podemos escribir y leer datos. Veamos de nuevo como se escriben
El código del procedimiento click del botón BIntroducir1 es :
Al leer los datos, lo primero es que no conocemos el número de registros existentes. Como cada
registro va en una línea del fichero, si contamos el número de retornos de carro (Chr(13))
obtendremos el número de registros. Esta operación es la primera que se realiza en el
procedimiento click del botón LEER :
‘ Abre el fichero, lo lee entero y cuenta el número de retornos de carro. Existirán tantos apuntes
(registros) como retornos de carro existan, ya que cada registro ocupa una línea.
‘Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando a los elementos
‘que componen la matriz.
For I = 1 To NR
Input #1, REGISTROLIBROS(I).TITULO
Input #1, REGISTROLIBROS(I).AUTOR
Input #1, REGISTROLIBROS(I).EDITORIAL
Input #1, REGISTROLIBROS(I).EDICION
Input #1, REGISTROLIBROS(I).PRECIO
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 10
Input #1, REGISTROLIBROS(I).EXISTENCIAS
Next I
Close #1
‘NRP = Número del Registro Presentado. Lo hacemos igual a 1 para presentar, de momento, el
‘número 1
NRP = 1
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Observe que es muy sencillo trabajar con ficheros secuenciales para bases de datos. El
inconveniente es la cantidad de memoria necesaria para la matriz de datos. También tienen un
gran inconveniente: solamente se pueden leer de hacia adelante. Un fichero secuencial hay que
leerlo de una sola vez. Esto que no es ningún inconveniente para un fichero de texto, o incluso
para un fichero de datos que leemos una única vez, es un problema cuando leemos un dato
situado en un punto de ese fichero, y luego tenemos que leer un dato colocado en una posición
anterior. En este caso, deberemos terminar de leerlo, y volver a comenzar por el principio. Este es
un gran inconveniente para hacer bases de datos con ficheros secuenciales.
No solamente hemos visto una forma de crear una base de datos, sino que hemos visto como
movernos a lo largo de los registros. Verá esto con mucho mas detalle cuando demos bases de
datos. Este tipo de bases de datos son la Tipo Texto que verá mas adelante.
EOF
Indica el fin del fichero (End Of File). EOF será False hasta que encuentre el final del
fichero secuencial. Habrá observado instrucciones tales como:
Estas expresiones se usan en un bucle, para ir extrayendo con la instrucción Input o Line
Input los caracteres de un fichero hasta que se encuentre la marca de final de fichero
(EOF)
LOC
Devuelve la posición de lectura/escritura actual en un archivo abierto.
LOF
Devuelve la longitud de un fichero (Lenght Of File) abierto mediante Open.
Sintaxis LOF(numeroarchivo)
SEEK
Devuelve la posición actual de lectura/escritura de un archivo abierto con la instrucción
Open.
Sintaxis Seek(númeroArchivo)
Seek devuelve un valor entre 1 y 2,147,483,647 (equivalente a 2^31-1) inclusive. Para archivos
abiertos en modo Output, Append o Input, Seek devuelve la posición de byte en la que se va a
ejecutar la siguiente operación. El primer byte de un archivo está en la posición 1, el segundo en la
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 12
posición 2 y así sucesivamente.
FICHEROS ALEATORIOS (RANDOM)
Un fichero aleatorio es un conjunto de registros, todos ellos de la misma longitud, que nos
permite guardar varias colecciones de datos.
Tal como habíamos visto en los ficheros secuenciales, el almacenar una serie de colecciones de
datos en un fichero secuencial era muy fácil, pero bastante difícil de almacenarlas en la memoria
cuando el número de estas colecciones superaba una cierta cantidad.
Los ficheros aleatorios permiten almacenar información en registros que pueden ser fácilmente
leídos, pudiendo leer los registros uno a uno, sin necesidad de leerlos todos. En los archivos
secuenciales, la información de varios datos podíamos introducirla mediante la instrucción Write, y
conseguíamos un registro de la forma: (Recuérdese el ejemplo de los datos de un libro)
"Título","Autor","Editorial","Edición","Precio","Existencias"
Los ficheros aleatorios nos permiten guardar una información similar a la anterior, referida a
cualquier número de libros, y para leerla no es necesario leer todo el fichero, sino simplemente
acceder a los registros que nos interesen. También permite realizar el cambio de un registro de
una forma sencilla, sin alterar los demás.
Todo esto tiene un precio: En los archivos secuenciales, podíamos introducir informaciones de
cualquier longitud. En los archivos aleatorios cada dato tiene una longitud asignada, longitud que
no se puede sobrepasar, y si la información que debemos almacenar tiene menos que la longitud
preestablecida, perderemos esa capacidad sobrante.
Un fichero aleatorio (Random), una vez abierto, puede utilizarse para leer o escribir datos.
Para escribir datos en un fichero aleatorio, primero debemos definir el registro, es decir, en el caso
de los libros visto anteriormente, un registro va almacenar los datos del titulo, autor, editorial, etc.
Para "saber" como se colocan estos datos dentro del registro será necesario definirlo.
En realidad lo que vamos a hacer es definir una variable de las denominadas “Definidas por el
usuario” Con esto lo que hacemos es crear un nuevo tipo de variable, en el ejemplo, la variable
tipo Registro. Se debbe hacer en la sección de declaraciones de un módulo o de un formulario, y
siempre antes de declarar una variable como variable de ese tipo. (La definición de la variable
debe hacerse en la sección de declaraciones del módulo o formulario con ámbito suficiente para
que sea válida en todas las partes de la aplicación donde se necesite esa variable)
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 13
Podemos hacerlo con la instrucción Type:
Type Registro
Titulo As String * 30 Asignamos 30 caracteres para el título
Autor As String * 30 Otros 30 para el autor
Editorial As String * 15 Asignamos 15 caracteres para editorial
Edición As String * 6 Asignamos 6 caracteres para Edición
Precio As String * 4 Asignamos 4 caracteres para el precio
Existencias As String * 3 Tres caracteres para existencias.
End Type
Observe la diferencia de esta definición con la que hacíamos en los ficheros secuenciales. En
aquellos no poníamos la longitud de cada sección. Aquí es necesario, ya que la longitud de un
registro (y también de cada campo) es fija.
Ya una vez definido como es Registro, podemos decir que una variable es del tipo definido para
Registro, es decir :
Entonces MiVariable ya puede almacenar los datos de Titulo, Autor, Editorial, Edición, Precio y
Existencias, colocando un dato tras otro, sin ninguna separación, en el mismo orden que lo
habíamos definido para Registro. No es necesario utilizar separaciones ya que el programa sabe
que longitud tiene cada dato y el orden de colocación. Lo sabe porque se lo hemos dicho al definir
Registro. Si los datos a introducir son :
el registro correspondiente a este libro tendrá una forma mas o menos así :
donde se ha sustituido el carácter nulo por una barra ( / ) con el fin de hacerlo visible en el texto.
Si se molesta en contar los caracteres que tiene el registro observará que son 88, que es la suma
de 30 + 30 + 15 + 6 + 4 + 3 que son los caracteres asignados a cada uno de las partes que forman
el registro (Título, Autor, etc.) Para hablar con propiedad, a esas partes que componen el registro
lea vamos a llamar CAMPOS. Un Registro está formado por varios Campos, y cada Campo
contiene una información.
Imagínese que introducimos otro libro. El primer campo de ese nuevo registro se colocará en el
fichero inmediatamente después del último campo existente, sin ningún tipo de separación. No
hace falta esa separación, pues VB conoce donde finaliza un registro y comienza otro, ya que la
longitud total del registro se le ha introducido en la instrucción para abrir el fichero, que repetimos
aquí por comodidad :
LongitudRegistro deberá ser igual o mayor que la suma de caracteres de cada uno de los campos
declarados en la instrucción Type, que también reproducimos :
Type Registro
Titulo As String * 30 Asignamos 30 caracteres para el título
Autor As String * 30 Otros 30 para el autor
Editorial As String * 15 Asignamos 15 caracteres para editorial
Edición As String * 6 Asignamos 6 caracteres para Edición
Precio As String * 4 Asignamos 4 caracteres para el precio
Existencias As String * 3 Tres caracteres para existencias.
End Type
¿Deberá ser igual o mayor, o estrictamente igual ? La respuesta es igual o mayor. Pero si
declaramos en la instrucción Open que el registro es mayor que la suma de los caracteres de
todos los campos que lo componen, estaremos perdiendo espacio de disco duro, tanto como la
diferencia entre lo declarado en la instrucción Open menos la suma de los caracteres de cada uno
de los campos. Y esa cifra, multiplicada por el número de registros existentes. Por lo tanto debe
declararse en la instrucción Open exactamente la suma de los caracteres de todos los campos. En
el ejemplo anterior era bastante fácil, ya que todos los campos eran del tipo String (cadena de
caracteres) y cada carácter ocupa un byte. La cosa se complica si uno o varios de los campos son
de tipo numérico, porque nos obligará a recordar cuantos bytes ocupa un integer, un Long, etc. Si
hubiésemos declarado en la instrucción Type Precio as Long, Existencias as Integer deberíamos
tener en cuenta que un Long (número entero entre -2.147.483.648 y 2.147.483.647, inclusive)
ocupa 4 bytes y un integer (número entero entre -32.768 y 32.767) ocupa 2 bytes. Se reproduce a
continuación la longitud en Bytes de cada uno de los tipos de datos. No se moleste en
aprendérsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como Resumen de
tipos de datos. Pero fíjese en algo tan curioso como que un dato tipo Boolean que solamente
puede tomar 2 valores (Sí / No) ocupa 2 bytes frente a un dato tipo Byte, que puede tomar 256
valores y ocupa solamente un Byte.
Ya le estoy viendo tomando buena nota de cuanto ocupa cada variable. Y echando números para
saber la longitud exacta de la variable y no perder ningún byte del disco duro desaprovechándolo
sin información. ¿No habrá algo que nos lo facilite ? Sí, lógicamente. La instrucción LEN
Ni que decir tiene que si se abre ese fichero en varias partes del programa con distintas
instrucciones Open el valor de LongitudRegistro debe ser igual en todas ellas.
A partir de este momento, el programa sabe que REGLIBROS es una variable que tiene 6 campos
(Titulo, Autor, Editorial, Edición, Precio y Existencias) y que cada campo tiene los caracteres
especificados en la instrucción Type.
Ahora nos cabe una pregunta ¿Cuantos registros tiene un fichero Random? La respuesta es
sencilla. Basta conocer la longitud del fichero mediante la instrucción LOF si el fichero ya está
abierto, o con la instrucción FILELEN si no lo está, y dividir el dato obtenido con cualquiera de las
dos instrucciones anteriores por el valor LongitudRegistro.
Una vez abierto el fichero Random podemos leer y escribir datos en él. Para escribir datos
utilizaremos la instrucción Put. La sintaxis de Put es la siguiente:
Puede omitirse NumeroRegistro. En este caso, el número de registro que se escribirá será el
siguiente al último registro escrito.
Luego REGLIBROS tendrá 6 campos (Titulo, Autor, Editorial, Edición, Precio y Existencias), cada
uno de una longitud determinada, la definida en la instrucción Type.
Antes de introducir REGLIBROS en el fichero habrá que decir que valor tiene. Pero cada campo
que lo compone tendrá un valor. Podríamos hacer una aplicación en la que, a través de varios
TextBox, le introdujésemos los valores de los campos, y el número de registro en el cual queremos
escribir. El nombre de cada uno de los TextBox para cada uno de los datos es el siguiente :
La aplicación deberá introducir en cada campo el valor (string) existente en cada uno de esos
TextBox. El valor de la variable REGLIBROS lo compondremos de la siguiente forma :
REGLIBROS.Titulo = TBTITULO.Text
REGLIBROS.Autor = TBAUTOR.Text
REGLIBROS.Editorial = TBEDITORIAL.Text
REGLIBROS.Edicion = TBEDICION.Text
REGLIBROS.Precio = TBPRECIO.Text
REGLIBROS.Existencias = TBEXISTENCIAS.Text
(Si se hubiese omitido alguna de estas igualdades, el campo correspondiente contendría el valor
nulo)
De esta forma, REGLIBROS ya tiene un valor que se puede escribir en el fichero mediante la
instrucción Put.
Observe que ya se le han introducido otros controles (TextBox para introducir el nombre del
fichero, otro para el número de registro, botones para leer, escribir, abrir el fichero (EXAMINAR),
un par de botones para subir o bajar el número de registro y un botón para salir de la aplicación. El
TextBox para introducir el nombre del fichero se llama TBNOMBREFICHERO y en el que
debemos introducir el número de registro a leer o escribir TBLEERESCR.
El Botón EXAMINAR cierra cualquier fichero que pudiese estar abierto, abre el fichero indicado en
TBNOMBREFICHERO, calcula el número de registros y escribe este número en el Label con
nombre LNUMFICH. El código de su procedimiento Click es el siguiente :
Veamos como se escribe un registro. Analicemos el código del procedimiento click del botón
ESCRIBIR
Para leer los datos de un fichero Random utilizaremos la instrucción Get. Su sintaxis es la
siguiente :
Puede omitirse NumeroRegistro. En este caso, el número de registro que se leerá será el siguiente
al último registro leído.
La Instrucción Get leerá un registro completo. Ese registro contendrá varios campos, y
seguramente nos interesará conocer el valor de cada campo dentro de ese registro. Variable es
una variable que contendrá todos los campos. En nuestra aplicación de biblioteca, Variable tiene
por nombre REGISTROLIBRO (El mismo que tenía para la instrucción Put de escribir. Es pura
comodidad del programador. Puede tener cualquier otro nombre)
Para obtener el contenido de cada campo, realizaremos un proceso similar al empleado para la
escritura, pero al revés. En nuestra aplicación, pretendemos poner el contenido de cada campo
en los mismos TextBox que se utilizaron para escribirlos. Veamos el contenido del procedimiento
click del botón LEER
En los ficheros Random tienen especial importancia las funciones Seek y Loc.
Mediante la Función Loc podemos conocer la el último registro manipulado, bien por lectura,
escritura. Si abrimos el fichero y no se ha hecho ninguna lectura o escritura de registros, el número
devuelto por la función Loc es 0.
Variable tomará un valor igual al número del registro escrito o leído por última vez.
Mediante la Función Seek podemos conocer el próximo registro que será manipulado en una
operación de lectura o escritura. Si abrimos el fichero y no se ha hecho aún ninguna operación de
lectura o escritura, Seek devuelve el valor 1.
ATENCION
¡¡¡ Seek puede ser una función (lee un Dato) o una instrucción (fuerza un dato) ! ! !
Instrucción Seek
Sintaxis
EOF
Devuelve un valor que indica si se ha llegado al final de un archivo.
Sintaxis EOF(Numerocanal)
En archivos Random, EOF devuelve False hasta que se haya ejecutado una instrucción Get y no
haya podido leer el registro completo, en cuyo caso devolverá True.
La función EOF no suele emplearse en ficheros Random, ya que en estos nos movemos a base de
registros, y es muy fácil controlar cuantos registros existen en el fichero y en que registro nos
encontramos o nos vamos a mover, mediante las funciones LOF, LOC y SEEK
Recuerde Para obtener la longitud de un archivo que no está abierto utilíce la función
FileLen.
Un fichero binario es una sucesión de bytes, uno tras otro, que puede almacenar cualquier tipo de
información. Cuando se explicaban los ficheros secuenciales, decíamos que eran los mas
adecuados para introducir información de un texto, con los Random podíamos realizar una base
de datos de forma sencilla, a base de controlar los registros y sus campos. Con un fichero binario
podemos almacenar cualquier información. (texto y cualquier tipo de datos) .
Como siempre en VB, Numerocanal puede ser un número comprendido entre 1 y 255, que define
ea fichero. No pueden existir al mismo tiempo 2 ficheros abiertos con el mismo Numero de canal.
Una vez abierto un fichero se binario, podemos leer o escribir datos en él.
Para escribir uno o varios caracteres en un fichero binario, usaremos la instrucción Put.
- Si se puede conocer de antemano el número de bytes a escribir, puede declararse Variable como
un string de ese número de caracteres mediante la instrucción Dim, por ejemplo :
y en este caso siempre escribirá el número de bytes declarado. ¡ Cuidado ! Si los datos a
introducir sobrepasan el número de bytes declarados para Variable, los datos sobrantes no se
escribirán en el fichero. Si los datos a escribir en el fichero fuesen menos que los declarados para
Variable, la diferencia se rellenará con el byte nulo ( 0 ).
Pero en este caso debemos volver a decir ¡ Cuidado !, si no conocemos el número de bytes que
vamos a escribir, puede que “machaquemos” parte de la información que ya tenemos en el
fichero, pues la instrucción Put va a colocar los bytes que componen Variable en la posición
especificada por Posición y siguientes, hasta que quepa toda la cadena de bytes que le queremos
introducir. Si la posición en la que introducimos esos bytes es una posición intermedia, y no
controlamos bien el número de bytes a introducir y las informaciones que ya existen en el fichero
en las posiciones colindantes con las que vamos a introducir los datos, es muy probable que
perdamos esa información al introducir la nueva.
¿Qué pasará si el dato Posición indica una posición mayor que la que tiene realmente el fichero ?
Simplemente que rellenará las posiciones intermedias que se formarán con un byte (puede verlo
con el Block de Notas ÿÿÿ)
Un fichero binario es, como se decía al principio, una sucesión de bytes, que no tiene ningún tipo
de separación entre bytes. Cada dato (byte o conjunto de bytes) que introduzcamos en un fichero
binario se escribirá en el fichero tal y como se introducen. Machacando información ya existente
si no se controla bien donde se mete. Por lo tanto, aunque parece que los ficheros binarios pueden
ser mucho mas versátiles que los secuenciales y los Random, exigen mucho mas control que los
anteriores. Limite el uso de este tipo de ficheros a las aplicaciones en que sea realmente
imprescindible.
Donde Posición es el número del primer byte leído, que como en el caso de Put, si se omite,
tomará como valor el byte siguiente al usado en la última instrucción Get. Variable es el nombre
de una variable que contendrá los datos leídos.
Pueden leerse uno o varios Bytes, pero ahora surge un pequeño problema. ¿Como le decimos
cuantos bytes debe leer ? Sencillamente los especificados al declarar la variable . Imaginemos
que la declaración de la variable fue :
Con Variable declarada de esta forma, leerá 10 bytes a partir del byte Posición. (Incluido)
De esta forma, siempre leeremos un número determinado de caracteres (10 en el caso del
ejemplo). Esta es una limitación para el uso de Get. Esta función viene muy bien en aquellas
aplicaciones en las que tenemos que extraer un número fijo de bytes (En la práctica, en la mayor
parte de las aplicaciones se extrae de uno en uno)
Pero pueden existir aplicaciones en las que sea necesario leer una vez un número de caracteres, y
otra vez otro. Ese problema lo tenemos resuelto con la instrucción Input.
Mediante la instrucción Input podemos leer el número de caracteres que queramos, pero no
podemos controlar el byte de comienzo. Por lo tanto deberemos ayudarnos de la instrucción Seek
para posicionar el puntero de lectura encima del primer byte que queramos leer :
Por ejemplo, si queremos leer 35 bytes de un archivo binario, abierto con el número de canal 1,
comenzando por el byte 48 (el 48 será el primer byte leído), ejecutaremos las dos siguientes
instrucciones :
LSB Visual Basic - Guía del Estudiante Capítulo 6 Página 22
Seek (1), 48
Variable = Input (35, #1)
Al igual que se hizo para los ficheros secuenciales y Random, vamos a ver con un ejemplo
práctico como se manejan los ficheros binarios.
Con el botón ABRIR se abre el fichero deseado. Si no existe en el disco, lo crea, ya que la
instrucción
Open Nombrefichero For Binary As # Numerocanal
intenta abrir un fichero existente llamado Nombrefichero, y si este no existe, lo crea. Si existe el
fichero, presenta todo su contenido en el TextBox inferior, para poder tener una referencia de que
lugar ocupan los distintos caracteres (un fichero binario puede guardar cualquier byte, por lo que si
abre un fichero generado con cualquier programa puede ser que muchos de los bytes no
contengan información de un carácter, por lo que le recomendamos haga esta práctica con un
fichero creado por la misma práctica)
El botón CERRAR cierra el fichero. SALIR sale de la aplicación. El TextBox superior (variable)
sirve para introducir la variable a escribir en el fichero, o para presentar la variable leída en caso
de lectura . El TextBox posición sirve para indicar la posición del primer byte. Posición por defecto
presenta la posición que se extrae mediante la función Seek cada vez que se hace una lectura o
escritura en el fichero. Longitud de la variable permite introducir esa longitud, para leer mediante
la instrucción Input.
El botón ESCRIBIR escribe el dato Variable en el fichero, LEER (GET) lee un único byte, y LEER
(INPUT) lee una cadena de caracteres, de longitud la especificada en el TextBox Longitud de la
variable.
FORMULARIO. DECLARACIONES
Option Explicit ‘Obliga a declarar todas las variables
Dim LONGVAR As Integer ‘Se declara la variable LONGVAR
Dim COMIENZA As Long ‘Se declara la variable COMIENZA
Dim TESTO As String ‘Se declara la variable TESTO
Dim pospordef As Long ‘Se declara la variable pospordef
BOTON ABRIR
Private Sub BABRIR_Click()
CD1.ShowOpen ‘CD1 es un CommonDialog para buscar el fichero
Open CD1.filename For Binary As #1 ‘Abre el fichero indicado en CD1
TESTO = Input(LOF(1), #1) ‘Lee de un golpe el fichero y lo mete en la variable TESTO
TBFICHERO.Text = TESTO ‘Presenta el fichero en el TextBox TBFICHERO
End Sub
BOTON CERRAR
Private Sub BCERRAR_Click()
Close ‘La instrucción Close cierra todos los ficheros abiertos
End Sub
BOTON ESCRIBIR
Private Sub BESCRIBIR_Click()
TBVAR2.BackColor = RGB(255, 0, 0) ‘Pone el TB long. De la variable en rojo
Dim escribe As String ‘Declara la variable escribe como string, sin limitación
escribe = TBVAR1.Text ‘Pasa el contenido de TBVAR a la variable escribe
Put #1, Val(TBVAR3), escribe ‘Instrucción Put. Val(TBVAR3) es la posición del 1er byte
pospordef = Seek(1) ‘Analiza donde quedó el puntero del fichero
Lvar5 = Str(pospordef) ‘y pone este valor en la etiqueta Lvar5
End Sub
BOTON SALIR
Private Sub BSALIR_Click()
End ‘Sale de la aplicación.
End Sub
DIR
Devuelve el nombre de un archivo, directorio o carpeta que concuerda con el patrón o atributo de
archivo especificado o la etiqueta de volumen de una unidad de disco.
vbNormal 0 Normal.
vbHidden 2 Oculto.
vbSystem 4 Sistema
vbVolume 8 Etiqueta de volumen; si se especifica se ignoran todos los atributos
vbDirectory 16 Directorio o carpeta.
FILECOPY
Copia un archivo.
fuente Expresión de cadena que especifica el nombre de un archivo a copiarse puede incluir el
directorio o carpeta y la unidad de disco..
destino Expresión de cadena que especifica el nombre del archivo de destino se puede incluir el
directorio o carpeta y la unidad de disco.
FILEDATATIME
Devuelve una fecha que indica la fecha y hora en que un archivo fue creado o modificado por
última vez.
SintaxisVariable = FileDateTime(nombreRuta)
El argumento con nombre nombreRuta es una expresión de cadena que especifica un nombre de
archivo. Se puede incluir el directorio o carpeta y la unidad de disco.
FILELEN
Si el archivo especificado está abierto cuando se llama la función FileLen, el valor devuelto
representa el último tamaño de ese archivo cuando se guardó la ultima vez en el disco.
Para obtener la longitud de un archivo abierto, utilice la función LOF.
GETATTR
Devuelve un número, que representa los atributos de un archivo, directorio o carpeta o una
etiqueta de volumen.
Valores devueltos
0 vbNormal Normal.
1 vbReadOnly Sólo lectura.
2 vbHidden Oculto.
4 vbSystem Archivo de sistema.
16 vbDirectory Directorio o carpeta.
32 vbArchive El archivo ha sido modificado después de efectuar la última copia de
seguridad.
SETATTR
Las constantes y valores de atributos son los mismos que para la instrucción GetAttr
FREEFILE
Devuelve el siguiente número de archivo disponible para ser usado con la instrucción Open.
Sintaxis FreeFile[(númerodeintervalo)]