10 diciembre 2006

Visual Basic .NET - Dejemos todo al azar...

¿Alguna vez has escuchado alguna frase relacionada a los "azares del destino"? No sé que tan cierto es eso que el destino sucede al azar (algunos están en desacuerdo con esta idea, como lo está Amado Nervo en su poema "Vida nada te debo"), pero los programadores no creen en que hay tanto azar en las cosas porque, aunque es posible (y muy útil) hacer archivos que se puedan accesar de manera aleatoria, se obtiene solamente lo que se ha grabado en ellas.

A lo mejor ya los hice bolas con los poemas (lo mencioné como simple cultura general) y los programadores. La idea es que puedo crear archivos por medio de los archivos de programación (aunque ahorita me interesan los que se pueden hacer en Microsoft Visual Basic .net) que pueden ser accesados de manera aleatoria. Esto del acceso aleatorio es una manera rimbombante de decir que podemos accesar cualquier parte del archivo que se nos pegue la gana en el momento en que se nos pegue la gana. Como habrás notado si leíste algunos de mis posts anteriores, este tipo de archivo difiere de los archivos secuenciales en que éstos últimos solamente pueden ser leídos desde el principio hasta el final, o sea, no es permitido saltar a cualquier parte del archivo y agarrarnos leyendo. No es que un tipo de archivo sea mejor que otro: cada uno tiene sus propios usos.

Como no todo es al azar, los programadores decidieron ponerle cierta estructura a las cosas para que no todo fuera tan alocado. Gracias a estas estructuras, podemos usar un archivo de acceso aleatorio como una tabla de una base de datos.

Para ilustrar como funciona esto, hice una pequeña aplicación que le podría servir a la biblioteca personal de alguien. Esta es la imágen del programa en funcionamiento:



La aplicacion usa las cajas de texto para llenarlos de valores y guardar el registro o para mostrar los datos de un libro leído. Todo esto funciona por medio de los botones, pero solo para farolear y aumentar mi ego y autoestima, decidí también tener un menú contextual que sirva para hacer lo mismo. Así es el diseño del menú:



Ahora, vámonos al código. Pero, como diría Jack el destripador, vámonos por partes. Para empezar, esta es la estructura que voy a usar para guardar los datos de los libros y algunas variables globales que me van a ser útiles. Todo esto va a dentro del Public Class Form1.



No voy a redundar con una explicación acera de cómo se hacen las estructuras porque ya escribí acerca de ellos aquí. De las variables, solo quiero aclarar lo que guardar. Librote es la instancia de la clase Libro que voy a usar, NombreArch es una cadena que tiene el nombre del archivo (toda la ruta completa) y NoReg guarda el número de registros que están almacenados en el archivo.

Todo esto se inicializa en el Form1_Load como se ve en esta figura. Lo primero que hace es asignarle el nombre Biblioteca.tvr a la cadena NombreArch (fíjate que al usar el Directory.GetCurrentDirectory, estoy diciendo que ese archivo va a estar en la misma carpeta donde se encuentra el archivo .EXE de esta aplicación). Luego consigo un número de archivo disponible (con el FreeFile()) y lo abro. Se te fijas, el uso de FileOpen() cambia un poco en relación a su uso con los archivos secuenciales. Como en el código no se ve toda la instrucción, más adelante (después de este código). Luego cuento el número de registros y guardo en dato en NoReg. Para hacer esto, comienzo a leer todos los registros usando la instrucción FileGet(), uno a uno, e ir acumulando en NoReg cuantas veces he leído hasta llegar al final del archivo (uso EOF() para saber si ya llegué al final). Y no hay que olvidar cerrar el archivo al final. Esto lo hago con FileClose().

En este mismo bloque de código, puse lo que tiene el Form1_MouseDown que se va a encargar de mostrar el menú contextual chiroliro que puse.



Ahora sí: la instrucción FileOpen() completo :

FileOpen(NoArch,NombreArch,OpenMode.Random,OpenAccess.ReadWrite,OpenShare.Default,Len(Librote))


Arriba expliqué lo que contiene NoArch y NombreArch. OpenMode.Random indica que vamos a usar un archivo de acceso aleatorio, OpenAccess.ReadWrite indica que vamos a poder leer datos del archivo y escribir datos a él. OpenShare.Default maneja toda la movida que pasa cuando varias personas quieren abrir el archivo al mismo tiempo. Se puede bloquear de escritura, lectura, etc. Con el Default le estoy dejando la bronca a VBasic .NET y le digo que ahi le encargo la bronca, que lo resuelva como mejor le parezca. Al final, uso la función Len() para que me devuelva el tamaño en bytes de la estructura, o sea, el tipo de dato de la variable Librote (o sea, una instancia de la estructura Libro). Esto es muy necesario para poder manejar las estructuras en el archivo. Si no le digo cuanto mide cada registro, es imposible que lo pueda hallar a la primera cuando le digo "quiero el registro 1355 y lo quiero rapidito". En el archivo, mide le número de bytes que se tiene que "saltar" para leer ese registro, o sea, el tamaño de Librote * 1355. ¿Entendido? ¡Adelante pues con lo que sigue!

Para cada acción que puede realizar el usuario tengo dos eventos donde lo puede hacer ya sea puchurrando (nuevo verbo, jeje) el botón o usando el menú contextual farol. Por esta razón, hice funciones que hicieran estas tareas vanas y rutinarias. Aquí está el ejemplo del código de los eventos que pone en blanco a todas las cajas de texto de la ventana y luego los eventos que guardan la información que está en la pantalla. Está tan fácil, que ni necesita explicadera.


El código que limpia la ventana (muy original, se llama LimpiaVentana) no tiene ninguna ciencia. Limpia la ventana (o sea, quita cualquier resto de texto que haya quedado por allí... pensándolo bien, nunca hay texto por allí... en fin, esa es la idea) e inicializa la estructura en ceros. Después hay una función AsignaLibro que copia los valores que hay en Librote a las cajas de texto de la ventana.



Ahora sí, algo más interesante. A continuación está la función GuardaLibro que se encarga de meterlo en su lugar quesque-aleatorio en el archivo. Hace lo mismo que hace Form1_Load al principio: encuentra un número de archivo que se puede usar y abre el archivo. Después le asigna a Librote los valores que hay en los Textboxes y al final le agrega uno al número total de registros para poder poner allí, en esa posición del archivo (en este caso, al final) el contenido de Librote. Una vez terminado, escribo el registro usando la función FilePut(), lo cierro y uso la función que limpia la ventana.



Sería inútil en este mundo guardar cosas si no los voy a usar. Bueno, eso pasa en nuestras casas cuando vamos acumulando tilichero, pero en las computadoras intentamos reducir el tilichero al máximo. Depsués de divagar en tiliches, intento decir que es muy importante consultar los datos que almacenamos porque si no los consultamos, mejor dedíquense a otra cosa y no se esfuercen en hacer programas. Pero como queremos hacer algo útil, ahi va la manera de accesar los datos que hemos guardado.

Hay 3 botones (y 3 elementos del menú farol) que hacen diferentes consultas. Dos de ellas son muy similares, el que busca por el título y el que busca por el ISBN (nada que ver con el INSEN). Los dos hacen prácticamente lo mismo: van desde el principio del archivo leyendo registros y comparándolos con el título o ISBN dado en un InputBox chafa que puse allí (mi idea es la de ejemplificar, no la de hecer una aplicación 100% terminada y fresón). El funcionamiento es también muy similar a lo que expliqué en el Form1_Load(), así que escribo aquí el código de la función BuscaISBN.


La otra manera de buscar sería la de accesar de forma directa el registro que quiero y leer los datos, o sea, la función quesque aleatoria del archivo. Para hacer esto, hay de dos sopas: usar la función FileGet() con el último parámetro que indica el número de registro que quier leer o usar la función Seek() para moverse al lugar en el archivo donde está ese registro y luego usar el FileGet() sin el parámetro del número del registro. Como es un mero ejemplo, lo hice de las dos maneras en la función BuscaReg, quien es la función encargada de buscar un libro por número de registro.


Parece que es todo. Espero que esto les sea útil. Bike.

9 comentarios:

Unknown dijo...

tony con esta funcion Directory.GetCurrentDirectory (que sirve para meterlo en el directorio .exe) no da en vs 2008 o es lo mismo

Unknown dijo...

tony con esta funcion Directory.GetCurrentDirectory (que sirve para meterlo en el directorio .exe) no da en vs 2008 o es lo mismo

Tony Valderrama dijo...

Debería ser lo mismo.

Si necesitas más referencia, está esta página del MSDN (el único problema es que está en inglés):

http://msdn.microsoft.com/es-es/library/system.io.directory.getcurrentdirectory.aspx

Ojalá esto te haya sido útil. ¡Saludos!

Unknown dijo...

Hola saludos Tony espero todo este bien aqui de nuevo recurriendo a ti para pedirte ayuda.

Mi problema es lo siguiente tengo un formulario con 5 textbox llamados registro,nombre,apellido,cedula,direccion.

Al lado del textbox registro tengo un boton que se llama buscar.

Aqui viene mi pregunta como me conecto a una base de dato en access (OJO ya se, pero si puede haces ese paso en el ejemplo que me hagas) y realizar un consulta y que me lo cargue en los textbox.

Por ejemplo: tu eres el registro 225

Yo quiero que al poner en el tbRegistro.text 225 y le de clic al boton buscar que esta al lado salga en el formulario tus otros datos como nombre,apellido,cedula y direccion...

Por favor tony necesito de tu ayuda urgentw...

Tony Valderrama dijo...

José Manuel:

Checa este post que hice hace poco en mi blog, a ver si responde tus dudas:

http://tony-valderrama.blogspot.com/2010/10/visual-basic-net-adonet-y-access.html

¡Saludos!

Anónimo dijo...

hola, excelente articulo, muchas gracias por publicarlo.
¡saludos!

JairoGallego dijo...

Hola, Excelente tutorial, he estado haciendo un progarama similar pero quisiera saber cómo modificar y elminar un registro muchas gracias, saludos!!!!

Tony Valderrama dijo...

Estimado JairoGallego...

Modificar no tiene ningún problema: basta saber en qué posición está en el archivo, llenar la estructura con los nuevos datos y guardarlo en esa posición. Sería idéntico que el agregar uno nuevo, solo que en lugar de ponerlo al final (en este ejemplo uso la variable NoReg para saber el último), lo escribes en la posición donde está almacenado el registro original.

Para borrar, no hay forma fácil. Lo que se me ocurre es hacer una rutina que escriba en otro archivo todos los registros menos el que se desea eliminar, luego borrar el archivo actual y renombrar el nuevo para que tenga el mismo nombre del original.

No sé si con esto te aclaro las dudas. Espero que si. Si no, vuélveme a mandar un comentario con dudas más específicas y, si puedo, te oriento.

¡Saludos!

JairoGallego dijo...

Hola pues todo fue de maravilla, lo de eliminar no lo alcancé a hacer pero tus explicaciones fueron de gran ayuda, por acá te estaré consultando cada que tenga dudas, de verdad muchísimas gracias por tus aportes.

El Tony y sus ondas...

Related Posts Plugin for WordPress, Blogger...