Visual Basic - Guía del Estudiante Cap. 6 FICHEROS EN VISUAL BASIC Existen tres tipos de ficheros donde podremos almacenar y leer datos: - Secuenciales - Aleatorios (Random) - Binarios Cada uno de ellos tiene sus aplicaciones y particularidades. 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, igualmente, carácter carácter tras carácter carácter.. (Byte tras byte). Son los mas sencillos de manejar, manejar, y los utilizados para guardar texto en ASCII. Permiten guardar datos en un fichero con un determinado nombre, nombre, "machacando" "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 Para abrir abrir un fichero fichero secue secuencia nciall para para guarda guardarr informaci información, ón, debemos debemos ejecutar ejecutar la siguien siguiente te instrucción:
Open Nombrefichero For Output As # Numerocanal De esta forma, si ya existía un fichero llamado Nombrefichero, sobreescribiremos dicho fichero perdiendo la información que contuviese. Es la forma típica de hacerlo cuando modificamos un texto. Para añadir la nueva información tras la ya existente, deberemos abrirlo con la siguiente instrucción:
Open Nombrefichero For Append As # Numerocanal 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.
Para cerrar un fichero secuencial, basta con ejecutar la instrucción:
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 byte tal como se comentó. 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:
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 1
Print #NumerodeCanal, Text1.Text 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 abre el archivo con la instrucción Open
Open Nombrefichero For Input As # Numerodecanal Se utiliza la instrucción Input o Line Input para sacar los datos del fichero. La instrucción Input tiene en este caso la siguiente sintaxis: VariableString = Input (Numero de caracteres, # Numero de canal) 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 número 1 como como número de canal. canal. Recuerd Recuerde e que ese número número puede puede ser un número número comprendido entre el 1 y el 255
VariableString = Input (LOF (1) (1), #1) #1)
LOF( LOF(1) 1)=l =lon ongi gitu tud d del del fich ficher ero o #1 #1
leeremos leeremos el fichero de una única vez. Este procedimiento procedimiento puede puede ahorrarle cierto tiempo a la hora de la lectura. (Por lo dicho anteriormente anteriormente,, este procedimiento procedimiento de leer todo el f ichero 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 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.. La forma de hacer este bucle es la siguiente: Dim Dim A As Stri String ng A es la vari variab able le dond donde e met meter erem emos os el car carác ácte terr que que extr extrae aemo moss del del fiche fichero ro.. Dim MiVariable MiVariable as String MiVariable MiVariable es una variable tipo string string donde donde vamos a meter todo el contenido del fichero Do Until EOF(1) EOF(1) sea ficheros cuando puntero puntero de lectura que es el carácter siguiente
El programa ejecutará este bucle ha h asta que se s e cu c umpla que True. True. EOF(NumerodeC EOF(NumerodeCanal) anal) es una propiedad propiedad de los están ab abiertos, que es es Tr True cu cuando la la po posición de del apunta apunta al carácter carácter Fin De Fichero (End Of File) al último carácter de texto de ese fichero.
A = Input (1, #1)
Estrae un un ca carácter de del fifichero ab abierto po por el el ca canal nú número 1. 1. Al Al
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 2
leer este este tantos caracteres leído.
carácter carácter,, el puntero puntero de lectura avanza automáticament automáticamente e como haya leído, colocándose sobre el primer carácter no
MiVaria MiVariable ble = MiV MiVari ariable able & A
Con esta esta línea línea vamos vamos anexa anexando ndo el carác carácter ter leído leído a la variable variable MiVariable. En vez de utilizar una variable, variable , podríamos poner ese ese texto sobre un TextoBox TextoBox o un RichTextBox RichTextBox (RTB) (Lo verá proximamente). Si lo ponemos en un RTB esta línea sería: RTB.SelText RTB.SelText = A
Loop
Vuel ve al comienzo del bucle.
Close #1
Cierra el fichero
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, continuación, pues es la instrucción que deberá utilizar para leer archivos escritos con la instrucción Write ), Input devuelve todos los caracteres caracteres que lee, incluyendo incluyendo puntos y coma, retornos retornos de carro, carro, avances de línea, comillas y espacios iniciales. Existe una instrucción, 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.
INSTRUCCION LINE INPUT La instrucción Line Input se utiliza para extraer una línea completa. Tiene la siguiente sintaxis:
Line Input # Número de canal, VariableString Mediante esta instrucción se extrae una línea completa (los caracteres delimitados entre dos retornos de carro), 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 puede realizar un pequeño pequeño edito de textos. textos. Este sencillo sencillo editor tiene tiene un TextBox extBox llamado llamado TBTexto, donde podemos escribir el texto que queramos (con la propiedad propiedad MultiLine = True y ScrollBars ScrollBars = Vertical), Vertical), tres botones llamados BAbrir (1), (2 a y b) y (3), para para abrir el fichero y poner su contenido contenido en TBT TBTexto, exto, 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 conocer el nombre del fichero, fichero, ponemos ponemos un CommonDialog llamado llamado CD1, con un filtro CD1.Filter = “Ficheros de Texto |*.txt” LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 3
Para abrir el f ichero, y depositar su contenido en TBTexto pondremos este código en BAbrir : Private Sub BAbrir1_Click() Dim VarTexto arTexto As String S tring CD1.Filter = "Ficheros de Texto |*.txt" CD1.ShowOpen Open CD1.filename For Input As #1 VarTexto VarTexto = Input(LOF(1), #1) 'leemos todo el fichero de un golpe Close #1 TBTexto = VarTexto End Sub 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. Para leer carácter a carácter : Private Sub BAbrir_Click() Dim VarTexto arTexto As String S tring CD1.Filter = "Ficheros de Texto |*.txt" CD1.ShowOpen Open CD1.filename For Input As #1 Do Until EOF(1) ‘Hacemos un bucle de lectura hasta que encontremos EOF(1) ‘ Vea mas adelante la Propiedad EOF en Propiedades de los ficheros Secuenciales VarT VarTexto = Input(1, #1) 'leemos el fichero carácter a carácter TBTexto TBTexto = TBTexto TBTexto & VarTexto arTexto 'vamos añadiendo los caracteres leídos a TBTexto TBTexto Loop Close #1 End Sub (NOTA.- Lo expuesto funciona perfectamente, pero el hecho de meter en un TextBox carácter a carácter eterniza la aplicación. - Meter un texto en un TextBox o en un Label es una operación que tarda cierto tiempo. Si esa operación operación hay que hacerla hacerla una vez por carácter, carácter, puede puede tardar tardar mucho tiempo. Para evitar esto, cuando vaya a leer un fichero carácter a carácter, métalo primero en una variable y luego realice un volcado único de esa variable al TextBox o Label) Y podemos hacerlo también leyendo línea a línea con Line Input Dim VarTexto arTexto As String S tring CD1.Filter = "Ficheros de Texto |*.txt" CD1.ShowOpen Open CD1.filename For Input As #1 Do Until EOF(1) Line Input #1, VarT VarTexto 'leemos el fichero Línea a Línea TBTexto TBTexto = TBTexto TBTexto & VarTexto arTexto & vbCrLf 'vamos añadiendo las líneas leídas a TBTexto TBTexto '(Hay que introducir un retorno + avance de l ínea con cada línea ( vbCrLf), ya que VarTexto VarTexto no ‘contiene los retornos ni avances de línea. Loop Close #1 Los Botones de Guardar tienen el código : Private Sub BGuardar_Click() Dim VarTexto arTexto As String S tring LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 4
CD1.Filter = "Ficheros de Texto |*.txt" CD1.ShowSave Open CD1.filename For Output As #1 Print #1, TBTexto.Text TBTexto.Text Close #1 End Sub O para el caso de abrir con For Append Private Sub BGuardar2_Click() Dim VarTexto arTexto As String S tring CD1.Filter = "Ficheros de Texto |*.txt" CD1.ShowSave Open CD1.filename For Append As #1 Print #1, TBTexto.Text TBTexto.Text Close #1 End Sub Ya hemos visto como se guardan y se leen datos de texto en un fichero secuencial.
INSTRUCCIÓN WRITE La otra forma de introducir datos en un fichero secuencial es Write. Mediante esta instrucción, no se puede introducir introducir texto, sino datos, aunque aunque esos datos sean sean de texto. Mediante Mediante la instrucción instrucción Write puede crear una pequeña base de datos. Eso sí, una base de de datos de escasa 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 : “Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51” “Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27” 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: Private Sub Command1_Click() TITULO = LIBRETBTITULO.Text LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 5
AUTOR = LIBRETBAUTOR.T LIBRETBAUT OR.Text ext EDITORIAL = LIBRETBEDITORIAL.T LIBRETB EDITORIAL.Text ext PRECIO = LIBRETBPREC.Text EXISTENCIAS = LIBRETBEX.Text ‘Donde LIBRETBTITULO, LIBRETBAUTOR, Etc. son los nombres de los TextBox TextBox ‘Ha leído los datos de los TextBox. Ya Ya están el las variables va riables TITULO, AUTOR, Etc. ‘Ahora los metemos en el fichero con la instrucción Write. El nombre del fichero será el ‘que hayamos puesto en el TextBox TextBox LIBRETBFICHERO, y lo guardará en el d irectorio ‘C :\cursoVB
Open TBNombreFichero.Text For Append For Append As #1 Write #1, TITULO, AUTOR, EDITORIAL, PRECIO, EXISTENCIAS Close #1 End Sub Si introduce los datos del ejemplo anterior, se creará un fichero que tiene esta apariencia: “Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51” 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: “Luis Suárez”,” VisualBasic - Guía del estudiante”,”Editorial XX”,”3200”,”51” “Miguel de Cervantes”,”El Qijote”,”Editorial YY”,”5000”,”27” ¿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 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, apro vechando los mismos TextBox: TextBox: Private Sub Command2_Click() ' Limpiamos Limpia mos los TextBox TextBox LIBRETBTITULO.Text = "" : LIBRETBAUTOR.Text = "" : LIBRETBEDITORIAL.Text = "" LIBRETBPREC.Text = "" : LIBRET BEX.Text BEX.Text = "" 'Abrimos el fichero
Open TBNombreFichero.Text For Input As #1 Do Until EOF(1) ' Introducimos una parada para poder leer datos DETENERSE = True Input #1, TIT, AUT, AUT, NED, PRE, EXS 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 LIBRETBEX.Text = EXS ' Refrescamos los TextBox Refresh ' Esto produce una pequeña parada Do While DETENERSE = True A=A+1 If A = 100000 Then DETENERSE = False: A = 0 Loop ' terminó la parada y vuelve a leer datos 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, escritura, y que el orden de las variables sea correcto 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 Observe también que se ha introducido introducido un temporizador. temporizador. Sirve para ver los sucesivos 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 mane jar 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 leyen leyendo do del del fiche fichero ro.. Inte Interr rrump umpía íamos mos moment momentán ánea eame ment nte e la lectu lectura ra para para pres presen enta tarr cada cada información durante un instante, ya que como tenemos cinco datos distintos en cada registro y cinco TextBox TextBox para presentarlos, deberemos presentar 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 : "EL RODABALLO","GUNTER GRASS","PLANETA",”1995”,2000,12 " VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21 "EL NOMBRE DE LA ROSA","UMBERTO ECO","AGUILAR",”28”,1000,21 LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 7
"ENCICLOPEDIA DEL VB","CEBALLOS","RAMA",”CUARTA”,1200,23 VB","CEBALLOS" ,"RAMA",”CUARTA”,1200,23 "LA GRANJA ANIMAL","ORWELL","DESTINO",”45”,12000,78 "LA PASION TURCA","ANTONIO GALA","PLANETA",”SEGUNDA”,2500,25 "LA METAMORFOSIS","KAFKA","PLAZA&JANES", “4ª”,3400,101 "VB4 PARA WINDOWS95","GARY CORNELL","MCGRAWHILL",”1ª”,6500,25 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. La interfaz gráfica quedó de la siguiente forma :
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 El fichero anterior podemos leerlo tal y como indicábamos antes :
Open TBNombreFichero.Text For Input As #1 Do Until EOF(1) Input #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS 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 : " VisualBasic - Guía del Estudiante ","LUIS SUAREZ","CEU",”PRIMERA”,1000,21 LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 8
los cuatro primeros parámetros van entre comillas dobles, ya que son datos tipo texto, y los dos últimos van sin comillas, como corresponde a datos numéricos. 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 tempor izador 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 necesitamos no es de ningún tipo de esos. esos. Está compuesta compuesta por varias secciones, 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 Observe que al usar paréntesis al declarar la variable REGISTROLIBROS REGISTROLIBROS le estamos diciendo a VB que esa variable será un Array, y además que es una variable del tipo REGISTROLIBRO, tipo de variable que ya conoce, puesto que se la hemos definido en un módulo. 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 : Private Sub BIntroducir1_Click() TITULO = LIBRETBTITULO.Text AUTOR = LIBRETBAUTOR.T LIBRETBAUT OR.Text ext EDITORIAL = LIBRETBEDITORIAL.T LIBRETB EDITORIAL.Text ext EDICION = LIBRETBEDICION.Text PRECIO = Val(LIBRETBPREC.T al(LIBRETBPREC .Text) ext) EXISTENCIAS = Val(LIBRETBEX.Text) Val(LIBRETBEX.Text) LSB
Visual Basic - Guía del Estudiante
‘TextBox para introducir el título ‘TextBox ‘ autor ‘ editorial ‘ edición ‘ precio ‘ e x i s te n c i a s Capítulo 6
Página 9
‘(Observe que para introducir el precio y las existencias se transformó el contenido del TextBox a ‘un valor numérico mediante la instrucción Val.) Open "C:\cursoVB\" + LIBRET BFICHERO.Text BFICHERO.Text For Append As #1 Write #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS Close #1 End Sub Tras reiteradas entradas, el fichero de la BD quedó como se vio anteriormente. Al leer los datos, lo primero es que no conocemos el número de registros existentes. Como cada regist registro ro va en una línea del fichero, fichero, si contam contamos os el número número de retorn retornos os de carro carro (Chr(1 (Chr(13)) 3)) obte obtend ndre remo moss el núme número ro de regis registr tros os.. Esta Esta oper operac ación ión es la prime primera ra que que se reali realiza za en el procedimiento click del botón LEER : Private Sub Command2_Click() LIBR LIBRET ETBTI BTITU TULO LO.T .Tex extt = "" "" ‘Pon ‘Pone e tod todos os los los Tex TextB tBox ox en en blan blanco co LIBRETBAUTOR.Text = "" LIBRETBEDITORIAL.Text = "" LIBRETBEDICION.Text = "" LIBRETBPREC.Text = "" LIBRETBEX.Text LIBRETBEX.Text = "" NR = 0 ‘ NR=número de registros ‘ 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. Open TBNombreFichero.Text For Input As #1 Do Until EOF(1) A = Input(1, #1) If A = Chr(13) Then NR = NR + 1 Loop Close #1 ‘ Presenta en LNumFich el número de registros LNumFich.Caption = Str(NR) + " Registros)" 'Redimensionamos la matriz de REGISTROLIBROS a NR elementos.. ReDim REGISTROLIBROS(1 To NR) ‘Volvemos a abrir el fichero Open TBNombreFichero.Text For Input As #1 ‘Leemos ‘Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando asignando a los elementos 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 NOTA.NOTA.- Estas líneas podríamos heberlas puesto en una línea única : Input#1,REGISTROLIB Input#1,REGISTROLIBROS(I).TITULO,R ROS(I).TITULO,REGISTROLIBROS EGISTROLIBROS(I).AUTOR, (I).AUTOR,_ _ REGISTROLIBROS(I).EDITORIAL,REGISTROLIBROS(I).EDICION,_ REGISTROLIBROS(I).PRECIO, REGISTROLIBROS(I).EXISTENCIAS
‘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 Copiamos este código de presentación de datos y lo llevamos a las flechas de incrementar o disminuir el e l número del registro a presentar. presentar. Private Sub BMas1_Click() NRP = NRP + 1 If NRP NRP > NR NR Then Then ‘pro ‘prote tegem gemos os que que salg salga a err error or de NRP fuer fuera a de de int interv ervalo alo MsgBox "No existen mas m as registros en esta dirección" NRP = NR Else 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 If End Sub Esta es la de incrementar. La de disminu ir es igual, pero restando 1 a NRP Las flechas dobles llevan al registro 1 y al último. Tienen este código Private Sub BMas2_Click() NRP = NR 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 LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 11
End Sub Observe Observe que es muy sencillo sencillo trabaja trabajarr con ficheros ficheros secue secuencial nciales es para para bases bases de datos. 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 bases de datos son la Tipo Texto que verá mas adelante.
Propiedades de los ficheros Secuenciales: 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: (Hazlo hasta que encuentres el EOF del canal 1) Do until EOF(1) Do While Not EOF(1) (Hazlo mientras EOF del canal 1 sea False) 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. La sintaxis de esta propiedad es: LOC (Numero de canal) la información devuelta para un archivo secuencial es la posición de byte actual en el archivo, dividida por 128.
LOF Devuelve la longitud de un fichero (Lenght Of File) abierto mediante Open. Sintaxis
LOF(numeroarchivo)
Ejemplo Long = LOF (1) ObservacionesPara obtener la longitud de un archivo que no está abierto utilice la función
FileLen . (Véala mas abajo) 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 ALEA ALEATORIOS TORIOS (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 bastante difícil de almacenarlas 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" Si deseáb deseábamo amoss guarda guardarr la informaci información ón de muchos muchos libros, libros, no había había mucho mucho problema problema para guardarla, pero sí para almacenarla en memoria para poder usarla luego. Teníamos que leer todo el fichero, y extraer de él la colección colección de informaciones informaciones y guardarlas guardarlas en una matriz. Cambiar una información dentro del fichero secuencial también implica una complicación adicional, ya que debemos debemos rehacer el fichero completo, pues un f ichero secuencial secuencial no permite “remendar” “remendar” el trozo que queremos cambiar. 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 cualquier longitud. longitud. En los archivos aleatorios cada dato tiene una longitud asignada, 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. Para abrir un fichero aleatorio debemos emplear la expresión:
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro Nombrefichero es el nombre que queremos dar al fichero Numerocanal es el número del canal (número de fichero) que puede ser de 1 a 255 LogitudRegistro es la longitud total del registro.
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 definirl o. En realidad lo que vamos a hacer es definir una variable de las denominadas “Definidas por el usuario” usuario” Con esto esto lo que hacemos es es crear un nuevo nuevo tipo de variable, en el ejemplo, la variable tipo Registro. Se debbe hacer hacer en la sección sección de declaraciones de de un módulo o de un formulario, formulari o, y siempre siempre antes de declarar declarar una una variable como variable de ese tipo. (La definición definición de la variable debe hacerse hacerse en la sección de declaracione declaracioness 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 Autor As String * 30 Edit ditorial rial As Stri tring * 15 Edición As String * 6 Precio As String * 4 Exis Existtenci encia as As Str Strin ing g *3 End Type
Asignamos 30 caracteres para el título Otros 30 para el autor Asign ignamo amos 15 caracteres para ed edito itorial ial Asignamos 6 caracteres para Edición Asignamos 4 caracteres para el precio Tres car caract acteres eres para para exis existtenci encias as..
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 : Dim MiVariable as Registro 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 porque se lo hemos dicho al definir Registro . Si los datos a introducir son : Titulo : Autor : Editorial : Edición : Precio : Existencias :
Guía del Estudiante Luis Suárez Bernaldo Ediciones XX 2ª 3500 25
el registro correspondiente a este libro tendrá una f orma mas o menos así : Guía del Estudiante///////////Luís Suárez Bernaldo//////////Ediciones XX///2ª////350025/ donde donde se ha sustituido sustituido el carácter carácter nulo por una barra barra ( / ) con el fin f in 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 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 :
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 14
(Si se omite el dato LongitudRegistro VB colocará la longitud por defecto, 128 caracteres) 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 Autor As String * 30 Edit ditorial rial As Stri tring * 15 Edición As String * 6 Precio As String * 4 Exis Existtenci encia as As Str Strin ing g *3 End Type
Asignamos 30 caracteres para el título Otros 30 para el autor Asign ignamo amos 15 caracteres para ed edito itorial ial Asignamos 6 caracteres para Edición Asignamos 4 caracteres para el precio Tres car caract acteres eres para para exis existtenci encias as..
¿Deberá ¿Deberá ser igual o mayor, o estrictamente estrictamente igual ? La respuest respuesta a 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 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) 32.767) ocupa 2 bytes. Se reproduce reproduce a conti continu nuaci ación ón la longi longitu tud d en Bytes Bytes de cada cada uno uno de los los tipos tipos de dato datos. s. No se molest moleste e en aprendérsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como Resumen de tan curioso como que que un dato tipo Boolean que solament solamente e tipos de datos . Pero fíjese en algo tan 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. Tipo de Dato Byte Boolean Integer Long(entero largo) Single(coma flotante Simple precisión) Double(coma flotante Doble Precisión) Currency Date Object String (longitud variable) String (longitud fija) Variant (con números) Variant (con caracteres)
Ocupa 1 byte 2 bytes 2 bytes 4 bytes 4 bytes 8 bytes 8 bytes 8 bytes 4 bytes 10 bytes + longitud de cadena longitud declarada de la cadena 16 bytes 22 bytes + longitud de cadena
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 LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 15
LEN nos da la longi tud de un texto (Var=Len (“Hola que tal”), o de una variable variab le Var=Len(Variable) Var=Len(Variable) Podemos usarla para conocer la longitud total de la variable MiVariable LongitudRegistro = Len (MiVariable)
Pero si quiere reducir mas la cosa, abra el fichero de esta forma :
Open Nombrefichero For Random As # Numerocanal Len = Len (MiVariable) 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. La decla declara ració ción n del regis registr tro o media mediant nte e la instr instruc ucció ción n Type Type debe debe hace hacers rse e en la secci sección ón de declaraciones de un Módulo. Esta instrucción Type Type en realidad lo que está haciendo es definir un nuevo tipo de variable, (una variable definida por el usuario) que servirá de “muestra” para que en otra parte del programa le digamos, mediante una instrucción Dim, que tal variable es del tipo definido anteriormente mediante la instrucción Type. Por lo tanto, debemos declarar una variable en la parte que corresponda del programa, dependiendo del ámbito que se le quiera dar a esa variable, diciendo que será del tipo de la declarada mediante la instrucción Type. Usando la declaración de Registro del ejemplo anterior, vamos a retomar el ejemplo de la bibliote biblioteca. ca. Declara Declararem remos os (posibl (posibleme emente nte en la sección sección de declara declaracion ciones es del formulari formulario) o) una variable que llamaremos p.e. REGLIBROS de la siguiente forma : Dim REGLIBROS as Registro A partir de este momento, el programa sabe que REGLIBROS es una variable que tiene 6 campos (Titulo, (Titulo, Autor, Autor, Editorial, Edición, Precio y E xistencias) xistencias) y que cada campo tiene los caracteres 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. Escribir datos en un fichero Random. Random. Instrucción Put
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:
Put # Numerocanal , NumeroRegistro, Variable Puede omitirse NumeroRegistro. En este caso, el número de registro que se escribirá será el siguiente al último registro escrito. NumeroRegistro es el número del registro que queremos escribir, y Variable es el contenido de ese registro. registro. Siguiendo con nuestro nuestro ejemplo de biblioteca, Variable tiene en este caso el nombre
REGLIBROS, que no es un String ni un Integer, sino una variable definida por el usuario ya que la declaramos con Dim REGLIBROS as Registro . Por lo tanto, tanto, la variable REGLIBROS contendrá contendrá los mismos campos que habíamos declarado para Registro en la instrucción Type. Recuerde :
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 16
Type Registro Titulo As String * 30 Autor As String * 30 Edit ditorial rial As Stri tring * 15 Edición As String * 6 Precio As String * 4 Exis Existtenci encia as As Str Strin ing g *3 End Type
Asignamos 30 caracteres para el título Otros 30 para el autor Asign ignamo amos 15 caracteres para ed edito itorial ial Asignamos 6 caracteres para Edición Asignamos 4 caracteres para el precio Tres car caract acteres eres para para exis existtenci encias as..
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á tendrá un valor. Podríamos Podríamos hacer 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 TextBox para cada uno de los datos es el siguiente : Campo Título : TBTITULO Campo Autor : TBAUTOR Campo Editorial : TBEDITORIAL Campo Edición :TBEDICION Campo Precio : TBPRECIO Campo Existencias : TBEXISTENCIAS 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 siguiente forma : REGLIBROS.Titulo = TBTITULO.Text REGLIBROS.Autor = TBAUTOR.Text 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 .
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 17
El formulario de esa aplicación tendrá esta forma :
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 extBox para para introdu introducir cir el nombre nombre del fichero fichero se llama TBNOMBR TBNOMBREFIC EFICHERO HERO 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 de su procedimiento Click es el siguiente : Private Sub BEXAMINAR_Click() Close Open Open TBNO TBNOMB MBRE REFI FICH CHER ERO O For For Ran Rando dom m As As #1 #1 Len Len = 88 LONGITUDFICH = LOF(1) NUMREGS = LONGITUDFICH / 88 LNUMFICH.Caption = NUMREGS End Sub
‘Cierra cualquier fichero abierto ‘Abr ‘Abre e el fiche fichero ro dese desead ado o ‘Obtiene su longitud ‘Calcula el Nº. de registros ‘Pone ese Nº. en el Label
Veamos como se escribe un registro. Analicemos el código del procedimiento click del botón ESCRIBIR Private Sub BESCRIBIR_Click() REGISTROLIBRO.Titulo = TBTITULO.Text REGISTROLIBRO.Autor = TBAUTOR.Text REGISTROLIBRO.Editorial = TBEDITORIAL.Text REGISTROLIBRO.Edición = TBEDICION.Text REGISTROLIBRO.Precio = TBPRECIO.Text REGISTROLIBRO.Existencias = TBEXISTENCIAS.Text Put #1, Val(TBLEERESCR ), REGISTROLIBRO End Sub
‘Se asignan los valores de cada ‘uno de los campos de la variable ‘REGISTROLIBROS
‘Se escribe el registro
Observe que el Nº. de registro es el valor que figure en el TextBox TBLEERESCR LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 18
Leer datos en un fichero fichero Random. Instrucción Get
Para leer los datos de un fichero Random utilizaremos la instrucción Get. Su sintaxi sintaxiss es es la la siguiente :
Get # Numerocanal , NumeroRegistro, Variable 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 Instrucción Get leerá leerá un regis registr tro o compl complet eto. o. Ese Ese regi registr stro o cont conten endr drá á varios varios campo campos, s, 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, escritura, pero al revés. En nuestra nuestra aplicación, pretendemos pretendemos poner poner el contenido contenido de cada campo en los mismos TextBox que se utilizaron para escribirlos. Veamos el contenido del procedimiento click del botón LEER Private Sub BLEER_Click() Get Get #1, Val(T al(TB BLEER LEERES ESCR CR), ), REGI REGIST STRO ROLI LIBR BRO O ‘Lee ‘Lee el regi regisstro tro com complet pleto o TBTIT TITULO. LO.Text ext = REGISTRO ROL LIBRO.Titulo ‘Obtiene el valo alor del campo Titulo TBAUTOR.Text = REGI EGISTR STROLIB LIBRO RO..Autor ‘Autor, Editorial, Edición, Precio TBEDI TBEDITO TORI RIAL AL.T .Tex extt = REGIS REGISTR TROL OLIB IBRO RO.E .Edi dito tori rial al ‘y Exis Existe tenc ncia iass y los los pone pone en en los los TBED TBEDIICION CION..Text ext = REG REGIS ISTR TRO OLIBR LIBRO. O.Ed Edic ició ión n ‘Tex ‘TextB tBox ox corre orresspond pondie ient ntes es a cada ada TBPRECIO.Text = REGISTROLIBRO.Precio ‘dato TBEXISTENCIAS.Text = REGISTROLIBRO.Existencias End Sub
Funciones e instrucciones aplicables a los ficheros Random. Funciones Seek y Loc. 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. La sintaxis de la función Loc es : Variable =
Loc (Numerocanal)
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.
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 19
La sintaxis de la función Seek es : Variable =
Seek (Numerocanal)
ATENCION ¡¡¡ Seek puede ser una función (lee un Dato) o una instrucción (fuerza un dato) ! ! !
Instrucción Seek La instrucción Seek establece el próximo registro a leer o escribir en un fichero Random. Sintaxis
Seek (Numerocanal), posición posición es el número de registro que se va a leer o escribir en la siguiente operación. No acepta
el 0 como número de registro, el mas bajo debe ser el 1. Si se intenta forzar a la posición 0 dará un error.
Funciones de los ficheros Random: 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, registros, y es muy fácil controlar cuantos cuantos registros registros existen existen en el fichero y en que registro registro nos encontramos o nos vamos a mover, mediante las funciones LOF , LOC y SEEK
LOF
( Lenght Of File ) Devuelve la longitud de un fichero . Sintaxis
Variable = LOF(Numerocanal)
Mediante la función LOF podemos conocer el número de registros existentes en un fichero Random, dividiendo el valor devuelto por LOF por la longitud del registro declarada en la instrucción Open (LEN = longitud) Nº. Registros = LOF / longitud Recuerde
LSB
Para obtener la longitud de un archivo que no está abierto utilíce la función FileLen .
Visual Basic - Guía del Estudiante
Capítulo 6
Página 20
FICHEROS BINARIOS Un fichero binario es una sucesión de bytes, uno tras otro, que puede almacenar cualquier tipo de informaci información. ón. Cuando Cuando se explicab explicaban an los ficheros ficheros secuenc secuenciale iales, s, decíam decíamos os que eran 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 registros y sus sus campos. Con un fichero binario podemos almacenar cualquier cualquier información. (texto y cualquier tipo de datos) datos) . Para abrir un fichero secuencial se abre utilizando la instrucción :
Open Nombrefichero For Binary As # Numerocanal 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. Nombrefichero es el nombre completo del fichero, con su Path.
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.
Put # Numerocanal, Posición, Variable Donde Posición es el Byte donde comenzará la escritura, y Variable es el nombre de la variable que contiene el dato a escribir. escrib ir. Este dato puede ser un byte o varios bytes. Para escribir varios bytes podemos hacerlo de dos formas : - 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 : Dim Variable As String * numero de bytes 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 ). - Si no se conoce de antemano el número de bytes a escribir, podemos declarar la variable sin especificar el número de bytes que tiene, y de esta forma se escribirán todos los bytes que componen la variable :
Dim Variable As String Pero en este caso debemos volver a decir ¡ Cuidado ! , si no conocemos conocemos el número de 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. LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 21
Si se omite el dato Posición, se tomará como byte de inicio de la escritura el siguiente al último usado por la instrucción Put. Si quiere quiere omitir omitir este este dato, dato, debe debe cons conserva ervarr las comas comas que que lo separan :
Put # Numerocanal, , Variable ¿Qué pasará si el dato Posición indica una posición mayor que la que tiene realmente el fichero ? Simplemente Simple mente que rellenará las posiciones intermedias que se formarán con un byte (puede verlo con el Block de Notas 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á 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 secuenciale secuencialess y los Random, exigen mucho mas control que los anterio anteriore res. s. Limite Limite el uso de este este tipo tipo de ficheros ficheros a las aplicacion aplicaciones es en que que sea sea realmente realmente imprescindible. Para leer datos de un fichero binario, utilizaremos la instrucción Get.
Get # Numerocanal, Posición, Variable 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 cuantos bytes debe leer ? Sencillamente Sencillamente los especificados especificados al declarar declarar la variable . Imaginemos Imaginemos que la declaración de la variable fue :
Dim Variable As String * 10 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 aplicaci ones 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. Podemos leer caracteres de un fichero secuencial mediante la instrucción Input : Variable =
Input (Numero de bytes, # Numerocanal)
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 ayudarnos de la instrucción Seek para posicionar el puntero de lectura encima del primer byte que queramos leer :
Seek (Numerocanal), Número del primer Byte a 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) Variable contendrá ahora los 35 bytes deseados.
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. El formulario del ejemplo tiene esta forma :
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 abre un fichero fichero genera generado do con cualquier cualquier programa programa puede puede ser ser que muchos 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. LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 23
Se enumera a continuación el código de cada uno, dejando para las explicaciones del profesor en clase, o el estudio del alumno, la interpretación de cada una de susu partes. FORMULARIO. DECLARACIONES Option Explicit ‘Obliga a declarar todas las variables Dim Dim LON LONGV GVAR AR As Inte Intege gerr ‘Se ‘Se dec decla larra la la var varia iabl ble e LON LONGV GVAR AR Dim Dim COM COMIIENZA ENZA As Long ong ‘Se ‘Se decl declar ara a la vari variab able le CO COMI MIEN ENZA ZA Dim TESTO As String ‘Se declara la variable TESTO Dim Dim pospordef As Long ‘Se declar clara a la vari varia able ble pospordef BOTON ABRIR Private Sub BABRIR_Click() CD1.ShowOpen ‘CD1 es un CommonDialog para buscar el fichero Open Open CD1.file CD1.filenam name e For Bina Binary ry As #1 #1 ‘Abre ‘Abre el el fichero fichero indicad indicado o en CD1 TESTO TESTO = Inpu Input( t(LOF LOF(1 (1), ), #1) #1) ‘Lee ‘Lee de de un gol golpe pe el el ficher fichero o y lo mete mete en la varia variable ble TESTO TESTO TBFIC TBFICHER HERO. O.T Text = TESTO TESTO ‘Pre ‘Prese sent nta a el ficher fichero o en el Text TextBox Box TBFI TBFICH CHERO ERO End Sub BOTON CERRAR Private Sub BCERRAR_Click() Close End Sub BOTON ESCRIBIR Private Sub BESCRIBIR_Click() TBVAR2 TBVAR2.Ba .BackC ckColor olor = RGB(2 RGB(255, 55, 0, 0) Dim es escribe As String escribe = TBVAR1.Text Put Put #1, #1, Val(T al(TBV BVAR AR3) 3),, esc escri ribe be pospordef = Seek(1) Lvar5 = Str(pospordef) End Sub BOTON LEER (GET) Private Sub BLEER_Click() TBVAR2.B TBVAR2.BackColor ackColor = RGB(255, RGB(255, 0, 0) TBVAR2.Text = "1" If Seek(1) >= LOF(1) Then Seek #1, 1 End If Dim TEXTO As String * 1 If TBVAR3.Text <> "" "" Then COMI CO MIEN ENZA ZA = Val Val(T (TBV BVAR AR3. 3.T Text) ext) Else ElseIf If Lvar Lvar5. 5.Ca Capt ptio ion n <> <> "" "" The Then n COMI CO MIEN ENZA ZA = Val Val(L (Lva var5 r5.C .Cap apti tion on)) Else COMIENZA = Seek(1) End If Get #1, COMIENZA, TEXTO TBVAR1.Text = TEXTO pospordef = Seek(1) Lvar5 = Str(pospordef) End Sub LSB
‘La instrucción Close cierra todos los ficheros abiertos
‘Pone ‘Pone el TB TB long. De De la variable variable en rojo rojo ‘Declara la variable escribe como st string, sin limitación ‘Pasa el contenido de TBVAR a la variable escribe ‘In ‘Instr strucci ucción ón Put Put. Val Val((TBV TBVAR3) AR3) es la la po posici sición ón del 1er 1er byt byte e ‘Analiza donde quedó el puntero del fichero ‘y pone este valor en la etiqueta Lvar5
‘Pone en rojo rojo el TB TBVA TBVAR2 R2 (long. (long. de de la variable) variable) ‘e indica que la longitud leída es 1 ‘Si está al final del archi vo ‘pone el puntero en la posición 1 ‘ ‘Declara la variable TEXTO de un byte ‘Si se se le ha in indicado do donde titiene qu que co comenzar ‘le ‘le dice dice que que com comie ienc nce e en la pos posic ició ión n indi indica cada da en en TBV TBVAR AR3 3 ‘si no, si exi exist ste e po posici sición ón por def defecto ecto ‘le ‘le indi indica ca que que com comie ienc nce e en la la posi posici ción ón por por defe defect cto o ‘ si no ‘pone el puntero en la posición 1 (byte 1) ‘lee un byte ‘y lo presenta en TBVAR1 ‘busca la nueva posición por def ecto por def ecto ‘y pone ese valor en Lvar5
Visual Basic - Guía del Estudiante
Capítulo 6
Página 24
BOTON LEER (INPUT) Private Sub BLLERINPUT_Click() TBV TBVAR2. AR2.Ba Back ckCo Colo lorr = RGB RGB(2 (255 55,, 255 255,, 255 255)) ‘Pon ‘Pone e TBV TBVAR AR2 2 en en blan blanco co LONGVAR = Val(TBVAR2.T Val(TBVAR2.Text) ext) ‘pasa el valor para long. de variable a LONGVAR If TBVAR3.Text <> "" Then ‘si ese val valor exi existe (TBVAR3 es distinto de nada) COMI CO MIEN ENZA ZA = Val Val(T (TBV BVAR AR3. 3.T Text) ext) ‘la ‘la var varia iabl ble e COM COMIE IENZ NZA A tom toma a es ese val valor or Seek (1), COMIENZA ‘coloca el puntero en ese valor End If ‘ Dim TEXTO As String ‘Declara la variable TEXTO sin limitación TEXT TEXTO O = Inp Input ut(L (LON ONGV GVAR AR,, #1) #1) ‘Lee Lee LO LONG NGV VAR byte bytess del del cana canall 1 y los los pa pasa a TEXT TEXTO O TBVAR1.Text = TEXTO ‘y lo presenta en el TB TBVAR1 pospordef = Seek(1) ‘analiza la nue va posición por defecto Lvar5 = Str(pospordef) ‘y la presenta en Lvar5 End Sub ‘ BOTON SALIR Private Sub BSALIR_Click() End End Sub
‘Sale de la aplicación.
Private Sub TBVAR2_Change() TBVAR2_Change() TBV TBVAR2. AR2.Ba Back ckCol Color or = RGB( RGB(25 255, 5, 255 255,, 255) 255) End Sub
‘Vue ‘Vuelve lve a colo colorr blan blanco co si si intr introd oduci ucimo moss un dat dato o en ‘este Text Box
FIN DE LA APLICACIÓN PARA MANEJO DE FICHEROS BINAR IOS
Funciones y propiedades aplicables a todos los ficheros 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. Sintaxis
[(nombreruta[, atributos])] Dir [(
nombreruta
Expresión de cadena que especifica un nombre de archivo. Puede incluir el directorio o carpeta y la unidad de disco. Si no se encuentra nombreruta, devuelve Null.
atributos
Constante o expresión numérica, cuya suma especifica atributos de archivo. Si se omite, devuelve todos los archivos normales que satisfacen el nombreruta.
El argumento atributos t iene estas constantes y valores: Constante
Valor
Descripción
vbNormal v b H i dden vbSystem vbVo bVolume vbDirectory
0 2 4 8 16
Normal. Oculto. Sistema Etiqueta de de vol volu umen; si si se se es especifi ifica se se ig ignoran to todos lo los at atributos Directorio o carpeta.
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 25
En Microsoft Windows, Dir permite el empleo de los caracteres comodín '*' (múltiples caracteres) y '?' (un solo carácter) para especificar varios archivos. La primera vez que se llama a la función Dir se debe especificar el nombreruta, de lo contrario se produce un error. Si además se especifican atributos de archivo, se debe incluir el nombreruta. Dir devuelve el primer nombre de archivo que coincide con el nombreruta. Para obtener más nombr nombres es de archi archivo vo que que coinc coincida idan n con con el nomb nombre reru ruta ta,, se debe volver volver a llamar llamar a Dir sin sin argumentos. Cuando no hay más nombres de archivo coincidentes, Dir devuelve una cadena de caracteres de longitud cero. Cuando se devuelve una cadena de longitud cero, en las siguientes llamadas se debe especificar nombreruta o se producirá un error. Se puede cambiar el nombreruta sin haber obtenido todos los nombres de archivo que coinciden con el nombreruta actual. Sin embargo, no se puede llamar a la función Dir.
FILECOPY Copia un archivo. Sintaxis
FileCopy f uente, uente, destino
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. Si intenta utilizar la instrucción FileCopy en un archivo abierto actualmente, se produce un error.
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 Devuelve la longitud de un archivo en bytes. Sintaxis Variable = FileLen (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. 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. Sintaxis LSB
Variable =
GetAttr (nombreRuta)
Visual Basic - Guía del Estudiante
Capítulo 6
Página 26
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. Valores devueltos El valor devuelto por GetAttr es la suma de los siguientes valores de atributos: Valor
Constante
Descripción
0 1 2 4 16 32
vbNormal vbReadOnly vbHidden vbSystem vbDirectory vbAr bArchiv hive
Normal. Sólo lectura. Oculto. Archi vo de sistema. Directorio o carpeta. El archiv hivo ha ha si sido modifi dificcado después de efectu ctuar la últi últim ma co copia de de seguridad.
SETATTR Establece los atributos de un archivo. Sintaxis nombreRuta atributos
SetAttr nombreRuta;atributos
Expresión de cadena que especifica un nombre de archivo se puede puede incluir el directorio o carpeta y la unidad de disco. Constante o expresión numérica cuya suma especifica los atributos de archivo.
Las constantes y valores de atributos son los mismos que para l a instrucción GetAttr Si se trata de establecer los atributos de un archivo abierto, se producirá un error en tiempo de ejecución.
FREEFILE Devuelve el siguiente número de archivo disponible para ser usado con la instrucción Open. Sintaxis
FreeFile[(númerodeintervalo)]
El argumento númerodeintervalo especifica el intervalo desde el que el siguiente número de archivo libre se va a devolver. Se especifica 0 (predeterminado) para devolver un número de archivo en el intervalo 1 a 255, inclusive. Se especifica especifica 1 para devolver un número de archivo en el intervalo 256 a 511. Observac Observacion iones es Se usa usa FreeFile cuando se necesita proveer un número de archivo y se quiere asegurar que el número de archivo no está ya en uso.
LSB
Visual Basic - Guía del Estudiante
Capítulo 6
Página 27