Pregunta 1: ¿Cuántas funciones escribiste para tu último proyecto en PHP? No cuentes las de librerías de terceros
grep -r "function " --include="*.php" .|grep -v "./libs" |wc -l
1291
Pregunta 2: ¿Puedes sacar un listado de ellas, ordenado por los nombres de los ficheros en los que se encuentran?
grep -r "function " --include="*.php" .|grep -v "./libs" |sort >funciones.txt
Las dos líneas de código se explican casi por sí solas, en todo caso puede requerir una brevísima consulta a la ayuda de grep (grep --help), así que no me molestaré en explicar lo que ya está escrito allí. Una vez entendidas las opciones, se entiende muy fácilmente.
VAMOS A PONERLE PEGAS
1. En la primera solución se realizan dos llamadas al comando grep, cuando se podría hacer en una. Además, el primer grep obtiene líneas que luego desechará el segundo grep ==> Ineficiente.
2. Además de lo que se pretende, también muestra aquellas líneas que tengan la palabra 'function' seguida de un espacio, aunque estas estén entre comentarios ==> Aunque en mi caso es poco probable que se dé esa situación, sin embargo es algo potencialmente inexacto (si hay algún comentario en inglés conteniendo esa palabra)
Resumiendo: Ineficiente, potencialmente inexacto...
Y seguramente tiene muchas más pegas.
Y SIN EMBARGO... TE QUIERO
Pero tiene una ventaja brutal: es definitivamente rápido de hacer. Muy rápido. Y rápido, también, de ejecutar (en nuestro caso, dado el lote de ficheros con los que tengo que trabajar). Así que, ¿por qué hacerlo más complicado cuando una solución quick-and-dirty puede valer?
Y es que, a veces, lo perfecto es enemigo de lo bueno. O como dijo R. Gabriel, lo peor es lo mejor. Pero de esto ya hablaremos en otra ocasión.
martes, 3 de noviembre de 2015
martes, 27 de octubre de 2015
Por dónde se mueve la serpiente
Desde hace poco, estoy flirteando un poco con Python, y entre otras pruebas que estoy haciendo, tengo un programa que quiero que me funcione tanto en Linux como en Windows.
¿Cómo hacer que el programa sepa si está en una u otra plataforma? (Por ejemplo, para tratar con las rutas de ficheros, o para buscar determinados directorios de sistema que tienen nombres predefinidos...)
En realidad, para esas dos cosas que he dicho, debería usar variables del sistema o constantes predefinidas (separador de directorios, directorio del usuario... que tengo pendiente de investigar), pero es posible que aún y así todavía quiera seguir sabiendo cómo conocer en qué sistema operativo se está ejecutando el programa.
Simplemente hay que importar el módulo (librería) platform, e invocar el método system, que devolverá la cadena 'Windows' o 'Linux'.
Pues ya está. Aquí el listado:
Como podéis ver, hay otros métodos interesantes: uname, architecture y python_implementation, que nos pueden dar información que puede que necesitemos en algún caso. Aunque si queremos maximizar la portabilidad de nuestros programas, deberíamos usar esto lo menos posible, para no atarnos en demasía a una plataforma específica. Que sí, que luego siempre se acaba migrando, aunque uno no quiera. Y las dependencias de la plataforma son un lastre.
La llamada a uname devuelve un array con bastante información (contiene, entre otras, el tipo de sistema, como lo devuelve system).
La salida en Ubuntu la podéis ver aquí:
Y aquí en Windows 7:
Por último, avisar de que este código está hecho para Python 3, así que no olvidéis poner en la primera línea del archivo la ruta del ejecutable de python3. También os dejo aquí cómo indicar que el encoding del archivo es UTF-8, cosa que os será útil si trabajáis con eñes, tildes y otras 'cosas raras'. Simplemente hay que poner en las dos primeras líneas esto:
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
¿Cómo hacer que el programa sepa si está en una u otra plataforma? (Por ejemplo, para tratar con las rutas de ficheros, o para buscar determinados directorios de sistema que tienen nombres predefinidos...)
En realidad, para esas dos cosas que he dicho, debería usar variables del sistema o constantes predefinidas (separador de directorios, directorio del usuario... que tengo pendiente de investigar), pero es posible que aún y así todavía quiera seguir sabiendo cómo conocer en qué sistema operativo se está ejecutando el programa.
Simplemente hay que importar el módulo (librería) platform, e invocar el método system, que devolverá la cadena 'Windows' o 'Linux'.
Pues ya está. Aquí el listado:
1 import platform 2 print("Mostrar información sobre el ordenador") 3 4 # Windows o Linux? 5 if platform.system() == "Windows": 6 print("En Windows") 7 raiz = 'c:\\' 8 elif platform.system() == "Linux": 9 print("En Linux") 10 raiz = '/' 11 12 print('------------------------------------------------------------------------') 13 print(platform.uname()) 14 print('------------------------------------------------------------------------') 15 print('Arquitectura:') 16 print(platform.architecture()) 17 print('Implementación: ' + platform.python_implementation()) 18 print('------------------------------------------------------------------------')
Listado 1: Diferenciar entre Windows y Linux con platform.system()
Como podéis ver, hay otros métodos interesantes: uname, architecture y python_implementation, que nos pueden dar información que puede que necesitemos en algún caso. Aunque si queremos maximizar la portabilidad de nuestros programas, deberíamos usar esto lo menos posible, para no atarnos en demasía a una plataforma específica. Que sí, que luego siempre se acaba migrando, aunque uno no quiera. Y las dependencias de la plataforma son un lastre.
La llamada a uname devuelve un array con bastante información (contiene, entre otras, el tipo de sistema, como lo devuelve system).
La salida en Ubuntu la podéis ver aquí:
Y aquí en Windows 7:
Por último, avisar de que este código está hecho para Python 3, así que no olvidéis poner en la primera línea del archivo la ruta del ejecutable de python3. También os dejo aquí cómo indicar que el encoding del archivo es UTF-8, cosa que os será útil si trabajáis con eñes, tildes y otras 'cosas raras'. Simplemente hay que poner en las dos primeras líneas esto:
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
viernes, 9 de octubre de 2015
Enviar mensajes de Telegram desde una aplicación web
Seguro que muchos conocéis Telegram, esa aplicación de mensajería instantánea que intenta hacerle la competencia a WhatsApp, aunque de momento, todo sea dicho, no le llega ni a la suela de los zapatos en cuanto a popularidad, y esto a pesar de tener algunas características bastante superiores. Pero bueno, la historia de la tecnología está llena de ejemplos en los que un producto técnicamente superior se ve desbancado por otro técnicamente inferior, y es que no sólo los detalles técnicos pesan. Sin embargo, leo que Telegram va creciendo gradualmente, así que espero que algún día la mayoría de mis contactos se hayan mudado de WhatsApp a Telegram. Mientras tanto, a seguir con las dos aplicaciones
No quiero entrar en los detalles técnicos ahora, y la evangelización sólo la hago los domingos, así que mejor os remito a esta entrada en hipertextual.com donde explican razonablemente bien las diferencias más importantes entre ambas aplicaciones. Lectura muy recomendable.
http://hipertextual.com/2015/06/telegram-vs-whastapp
¿Ya la habéis leído? Bien. Ahora, vamos al turrón.
http://hipertextual.com/2015/06/telegram-vs-whastapp
¿Ya la habéis leído? Bien. Ahora, vamos al turrón.
1. Los bots de Telegram
El 24 de junio de este año Telegram lanzó una característica que no he podido investigar hasta hace tan solo unos días (muy por encima, eso sí, aunque suficiente para lo que yo quiero hacer): los bots. [https://telegram.org/blog/bot-revolution]
Fig1. Los bots de telegram: una innovación muy interesante
Estos bots son cuentas de Telegram detrás de las cuáles no hay una persona, sino un programa, y sin necesidad de un número de teléfono asociado. Y son ideales para muchas cosas. Entre ellas, para que tus programas te puedan mandar mensajes al móvil, por ejemplo, aunque según parece esta es la menor de las utilidades que tienen. Pero es la que hoy me interesa.
El proceso básicamente consiste en tres pasos: 1) crear el bot, 2) chatear (unirse) a él todos aquellos que quieran recibir los mensajes y 3) enviar y recibir mensajes como si no hubiera un mañana
Ok, pues manos a la obra.
2. Crear un bot
Para esto se utiliza el BotFather, el padrino-de-los-bots (confío en que no habrá que explicar el juego de palabras. Si no, dejad de leer y sacad de la biblioteca la serie de películas de "El Padrino").
Simplemente, hay que entrar en la dirección [https://telegram.me/botfather]
y seguir las instrucciones que nos va dando.
Veremos un mensaje tal que así
Fig. 2. El padrino nos recibe en su casa
Podemos interactuar con el BotFather "chateando" directamente, teniendo en cuenta que las órdenes comienzan con una barra /, o bien podemos usar el botón que os he señalado con una flecha en la figura 2.
Creamos el bot con /newbot y le damos un nombre
Fig. 3. El bot recién creado, de nombre "Cosicas"
A continuación le damos un nombre de usuario, que termine en "bot". Esto nos devolverá un token que necesitaremos pasar en las invocaciones al bot, para poder enviar mensajes. Lo copiamos y lo guardamos en un lugar seguro. Lo necesitaremos un poco más adelante.
Fig. 4. Al darle el nombre de usuario recibimos un token
El bot posee una serie de métodos que podemos invocar a través de la URL
https://api.telegram.org/bot<token>/METHOD_NAME
Donde METHOD_NAME puede ser uno de los métodos que podéis consultar en la referencia de la API (aquí [https://core.telegram.org/bots/api]).
Por ejemplo, invocando al método getMe podemos obtener información básica del bot, entre ella el ID que lo identifica:
https://api.telegram.org/bot<token>/getMe
En mi caso, esto:
Fig. 5. Uso del método getMe para extraer el ID de nuestro bot
3. Chatear con el bot
A continuación debemos unirnos a la "conversación" con nuestro bot. Para esto, pinchamos en el enlace que nos ha dicho el BotFather en la figura 4. Es un enlace del tipo telegram.me/CosicasBot (que a su vez redirige a https://web.telegram.org/#/im?p=@CosicasBot). Allí veremos un botón que nos servirá para iniciar nuestra conversación con el bot.
Fig. 6. Accediendo a la "conversación" con el bot
Pulsamos en INICIAR y
Fig. 7. Ya estamos conectados a nuestro bot. Listos para enviar mensajes.
Al iniciar el chat con el bot, ya podemos obtener nuestro identificador para que nuestro programa pueda enviarnos mensajes. El chat_id identifica a nuestro usuario en Telegram, y el bot necesita saber este chat_id para poder enviarnos mensajes. En una reciente actualización he leído que también se puede hacer con el nombre del usuario. Yo voy a explicarlo con el chat_id.
¿Y cómo obtenemos ese chat_id? Un pequeño truco que he visto es invocar al método getUpdates de nuestro bot, tal y como describimos en el apartado anterior. Eso debería producir una respuesta en formato JSON que, entre otras cosas, lleva nuestro chat_id. Es decir, abrimos un navegador y tecleamos la URL siguiente:
https://api.telegram.org/bot<token>/getUpdates
Y deberíamos ver algo así:
Fig. 8. Forma "chapucerilla" de obtener el chat_id
En el recuadro rojo tenéis el chat_id.
4. Enviar un mensaje
Bueno, pues parece que ya lo tenemos todo. Ahora ya podemos crear una página PHP sencilla que envíe mensajes al bot. Sería algo tan simple como:
Fig. 9. Código para enviar un mensaje al bot
Por supuesto, no es necesario que sea PHP, puede estar escrita en cualquier lenguaje. Lo necesario es simplemente invocar la URL que se construye en la línea 15.
Por último, abro ese fichero PHP en mi servidor web y me voy al Telegram en mi móvil, et voilà!
Fig. 10. Mi PHP enviándome mensajes al móvil, ¡qué tierno!
Bueno, pues ahí tenéis una forma rápida de enviar mensajes al móvil vía Telegram desde vuestros programas. Pero ojo a los bots, que parece que tienen un gran potencial mucho más allá de esto.
Por cierto, el bot que he usado de ejemplo voy a cargármelo ahora mismo, que no quiero que nadie empiece a mandarme basura. Quien quiera probarlo, que se cree el suyo propio.
Fig. 11. Borrando el bot de este ejemplo
Bueno, seguramente habré cometido varios errores en este artículo, pero acabo de empezar a pelearme con los bots (tampoco creo que les dedique mucho más, ya tengo lo que quería) y seguro que algunas cosas las iré aprendiendo mejor en los próximos días.
Y por hoy, basta de programación.
lunes, 17 de agosto de 2015
Localizar ficheros en Linux
Un programa que me parece una maravilla en Windows es Everything, y no he encontrado nada en Linux que se le parezca. No concibo una sesión de trabajo en mi ordenador Windows sin este programa. Ojalá aparezca algo similar para Linux.
Pero no todo está perdido en Linux. Aquí tenemos el programa locate, con el que podemos hacer cosas "parecidas" (aunque ya quisiera yo que tuviera la potencia y el bajo impacto en memoria y procesador que tiene Everything).
Un ejemplo: para localizar todos los ficheros de configuración de MySQL que hay en mi equipo, escribiría algo así:
Y la salida es algo como esto:
Si además quiero abrirlos todos ellos en un único paso, podemos hacer
Y se nos abriría una ventana como esta
Ojo: esto funciona porque gedit acepta múltiples parámetros en la línea de invocación. Si el visor que vamos a utilizar no soporta múltiples parámetros, habría que hacerlo de otra manera.
El nombre que se le pasa como argumento a locate es un patrón, no tiene por qué ser el nombre literal. Esto quiere decir que buscará ficheros que contengan el patrón especificado en su nombre. Por ejemplo, podríamos haber listado los ficheros anteriores tecleando un carácter menos:
Y el resultado sería el mismo, ya que los ficheros implicados CONTIENEN el patrón especificado
Fijaos que el patrón no es exactamente una expresión regular, ya que no hace falta poner el * para indicar que puede haber más caracteres después de la "n" y, sin embargo, así es cómo locate hace la búsqueda.
Si elimino la letra "n" del patrón, podemos ver que aparecen más ficheros
O sea, que es como si el patrón tuviera al principio y al final un * (o, para los que estáis más habituados al mundo SQL, como si se hiciera una búsqueda LIKE '%PATRON%')
Así, por ejemplo, si quiero buscar todos los ficheros JPG que tengo en el equipo, no hay que buscar con el patrón *.jpg, sino simplemente teclear
Y si lo que quiero es contar cuántos ficheros JPG tengo en el equipo, puedo añadir esto:
Si queremos, podemos utilizar expresiones regulares en el patrón utilizando la opción --regex. Así, para buscar todas las imágenes JPG que empiezan por "yellow" pondríamos algo como
Y el resultado, en mi equipo, son dos ficheros
Que podríamos haber abierto así:
Ojo: he utilizado como visor de las imágenes eog (Eye of Gnome) ya que éste soporta múltiples ficheros en una invocación. Sin embargo, shotwell, el visor por defecto de Ubuntu, no los soporta y daría un mensaje diciendo que hay parámetros de más en la invocación.
Al contrario que Everything, que monitoriza el sistema de ficheros constantemente (algo posible gracias al journal de NTFS), la base de datos de locate no se actualiza con tanta frecuencia. Ahora no tengo tiempo de investigarlo, pero me da a mí que se actualiza en cada reinicio del sistema. Lo que sí se puede hacer es actualizarla a mano con el comando updatedb:
(Lo de "sudo" he tenido que ponerlo porque si no me daba problema al crear algún fichero temporal).
Bueno, pues dicho todo lo anterior, ya podéis buscar rápidamente todos esos ficheros que os gustaría renombrar, por si las moscas...
Pero no todo está perdido en Linux. Aquí tenemos el programa locate, con el que podemos hacer cosas "parecidas" (aunque ya quisiera yo que tuviera la potencia y el bajo impacto en memoria y procesador que tiene Everything).
Un ejemplo: para localizar todos los ficheros de configuración de MySQL que hay en mi equipo, escribiría algo así:
$ locate my.cnf
Y la salida es algo como esto:
Fig. 1. Localizando todos los ficheros "my.cnf" en mi equipo
Si además quiero abrirlos todos ellos en un único paso, podemos hacer
$ locate my.cnf | xargs gedit
Y se nos abriría una ventana como esta
Fig. 2. Todos los ficheros my.cnf abiertos en gedit
Ojo: esto funciona porque gedit acepta múltiples parámetros en la línea de invocación. Si el visor que vamos a utilizar no soporta múltiples parámetros, habría que hacerlo de otra manera.
El nombre que se le pasa como argumento a locate es un patrón, no tiene por qué ser el nombre literal. Esto quiere decir que buscará ficheros que contengan el patrón especificado en su nombre. Por ejemplo, podríamos haber listado los ficheros anteriores tecleando un carácter menos:
$ locate my.cn
Fig. 3. Todos los ficheros my.cn* del equipo
Si elimino la letra "n" del patrón, podemos ver que aparecen más ficheros
Fig. 4. Aparecen otros ficheros que coinciden con el patrón *my.c*
O sea, que es como si el patrón tuviera al principio y al final un * (o, para los que estáis más habituados al mundo SQL, como si se hiciera una búsqueda LIKE '%PATRON%')
$ locate .jpg
Fig. 5. Listado de ficheros .jpg existentes en mi equipo
$ locate .jpg | wc -l
Fig. 6. ¿Más de 2.000 imágenes????
Si queremos, podemos utilizar expresiones regulares en el patrón utilizando la opción --regex. Así, para buscar todas las imágenes JPG que empiezan por "yellow" pondríamos algo como
$ locate --regex yellow.*.jpg
Y el resultado, en mi equipo, son dos ficheros
Fig. 7. Las imágenes JPG que comienzan por "yellow*"
Que podríamos haber abierto así:
$ locate --regex yellow.*.jpg | xargs eog
Ojo: he utilizado como visor de las imágenes eog (Eye of Gnome) ya que éste soporta múltiples ficheros en una invocación. Sin embargo, shotwell, el visor por defecto de Ubuntu, no los soporta y daría un mensaje diciendo que hay parámetros de más en la invocación.
Al contrario que Everything, que monitoriza el sistema de ficheros constantemente (algo posible gracias al journal de NTFS), la base de datos de locate no se actualiza con tanta frecuencia. Ahora no tengo tiempo de investigarlo, pero me da a mí que se actualiza en cada reinicio del sistema. Lo que sí se puede hacer es actualizarla a mano con el comando updatedb:
Fig. 8. Actualizar a mano la BD de locate
(Lo de "sudo" he tenido que ponerlo porque si no me daba problema al crear algún fichero temporal).
Bueno, pues dicho todo lo anterior, ya podéis buscar rápidamente todos esos ficheros que os gustaría renombrar, por si las moscas...
Fig. 9. Ficheros que hay que renombrar urgentemente
miércoles, 12 de agosto de 2015
Notificaciones en Ubuntu
El escenario
Llego al curro y me dicen que durante mi ausencia me ha llamado Claudia Schiffer para ver si le puedo hacer una sesión de fotos y darle cremita, que le apetecía a la zagala irse a la playa. Como no me ha localizado, ha pedido que por favor le devuelva la llamada, pero a una hora concreta, ya que cuando me llamó Claudia se iba a cortarse las uñas y no podría contestarme durante un rato. La hora a la que me ha dicho que la llame es dentro de 20 minutos.Yo llego, me siento delante de mi ordenador a
Hay varios programas en una distribución estándar Ubuntu que podemos utilizar para mostrar un mensaje. Combinando estos con sleep (esperar X segundos, en este caso los 20 minutos equivalen a 1200 segundos), puedo hacer esto que acabo de explicar. Los comandos que siguen están probados en una instalación estándar de Ubuntu 15.04. En todos los casos, abriré una consola, me mandaré el aviso y a continuación me pondré a "trabajar" en una hoja de cálculo, a esperar a ver qué pasa con la notificación.
1. notify-send
$ sleep 1200; notify-send "Llama a Claudia que te está esperando"
Esto mostrará uno de esos mensajes "globo" que aparecen en la esquina superior derecha de la pantalla y desaparecen al cabo de unos pocos segundos (Fig. 1).
Fig 1. Un globo avisándome de que tengo que llamar a mi musa
El problema puede ser que la notificación de globo, al no quitarle el foco a la ventana en la que estemos actualmente, sigamos concentrados en la pantalla y no lo veamos (aunque reconozco que es un poco difícil no verlo, la verdad).
2. xmessage
$ sleep 1200; xmessage "Llama a Claudia que te está esperando"Esto hará que salte un diálogo con un botón aceptar ("okay" en mi distro). Esta sí que roba el foco, así que no podemos ignorarla sin más. Eso sí, es posible que si con el ratón hacemos clic en otra ventana, la notificación quede tapada. Un problema que puede que hayáis apreciado es que la tilde del mensaje no sale correctamente. Normalmente, el mensaje saldrá en una esquina inferior (en diversas pruebas me ha salido tanto en la esquina inferior derecha como en la izquierda, sin que yo sepa muy bien por qué). Podemos usar la opción -center para que salga en el centro de la pantalla (Fig. 2).
Fig 2. Mensaje en el centro de la pantalla.¡Mis tildes!
3. zenity
El comando zenity permite lanzar diversos tipos de cuadros de diálogo desde nuestros scripts o desde una consola. El programa 'gdialog' es un envoltorio sobre 'zenity', así que mejor usar zenity directamente.
Estos diálogos pueden ir desde mostrar un simple mensaje al usuario (opción --info) hasta pedirle que introduzca algunos datos (un texto, una fecha [opción --calendar], elegir una opción de una lista...). Los valores devueltos por zenity se pueden capturar en el script invocante y asignarlos a una variable, por ejemplo, para trabajar con ellos (muy interesante).
Para mostrar un simple mensaje sin interés en capturar la salida, podríamos escribir algo así como:
$ sleep 4; zenity --info --text="Llama a Claudia que te está esperando"
Y veríamos algo similar a lo que se ve en la Fig. 3.
Fig. 3. Un diálogo de mensaje con zenity. Es tímido, se queda detrás
El problema es que zenity NO adquiere el foco, así que queda detrás de la ventana activa. Si ésta ocupa toda la pantalla... malo. También podéis ver en la fig. 3 que aparece un warning en consola. Esto no es un problema, pero no me gusta.
4. Conclusión
Tras unas cuantas pruebas, mi preferida para este tipo de recordatorios es notify-send combinada con sleep, pues me gustan esos globos que no interrumpen el trabajo y que son suficientemente visibles. Además, no hay que pasar ningún parámetro para que funcione bien, con lo cual es rápido de teclear y no hay que andar recordando opciones (o mirando la ayuda) como en zenity, por ejemplo.
Si tuviera que capturar información del usuario (un texto, el botón pulsado...) utilizaría seguramente zenity.
En cualquier caso, echadle un vistazo a la ayuda de las tres herramientas, que son altamente configurables. También existen muchas otras herramientas para hacer cosas parecidas, así que si éstas que os he presentado aquí no os resuelven del todo vuestros problemas, investigad un poco.
Bueno, os dejo, que ha llegado la hora de llamar a Claudia...¡ains, qué nervios!
viernes, 17 de julio de 2015
Cambiar el nombre del equipo en Ubuntu
El equipo en el que estamos trabajando tiene un nombre, que se puede consultar con el comando 'hostname' tanto en Linux como en Windows.
¿Y para cambiarlo?
En la última instalación de mi Ubuntu no estuve muy acertado al elegir el nombre de equipo, y ahora me gustaría cambiarlo.
Simplemente, hay que editar estos dos ficheros:
/etc/hostname
/etc/hosts
Y ya está.
Bueno, en mi caso, además tuve que reiniciar.
En Windows se puede cambiar desde la interfaz gráfica, en Propiedades de "Equipo" o "Mi PC" (según versión).
Gracias a la comunidad Ubuntu por esta información, que podéis consultar, junto con muchas otras cosas útiles, aquí. Aunque hay que reconocer que la web está un poco dejada...
viernes, 10 de julio de 2015
Aversión a las versiones
Escudos y bichos con alas encima: mismo tema, diferentes versiones
(Baeza, palacio de Jabalquinto)
Aunque resulte difícil de creer, hay usuarios que no saben con qué versión de Windows están trabajando.
- José, tengo no-recuerdo-qué-problema con el ordenador de mi casa. ¿Cómo lo arreglo?
- Hmm... ¿qué versión de Windows tienes? (ya paso de preguntar qué versión de "sistema operativo", porque entonces me toca explicar qué es eso)
- Pues... no sé... ¿el 2007?
- No, eso es el Office que tienes pirateado
Como diría Forges: Gensanta.
Parece una trivialidad saber la información del sistema operativo, o que puede que esto no tenga demasiado interés, pero el asunto puede traer más cola de lo que parece. Así que allá van algunas formas de saber la versión del Sistema Operativo con la que estás trabajando.
1. Windows, modo gráfico
Ir a Inicio / Panel de Control / Sistema
Dependiendo de la versión, verás una ventana u otra, pero en cualquier caso, por algún lado te debería informar acerca de la versión.
En Windows XP y Windows 7 se ve algo así:
Fig. 1. Información de la versión y algo más en Windows XP
Fig. 2. Información de la versión y algo más en Windows7
En ambos casos, además de la versión del SO, también se da información sobre el equipo como memoria, parches instalados, velocidad del procesador... En fin, que merece la pena echarle un vistazo.
2. Windows, modo ventana negra
La opción gráfica está bien para los usuarios "normales" pero, como informáticos, a veces puede que queramos utilizar la información de la versión en un programa, por ejemplo, un script que recupere esta información del SO y tome las decisiones oportunas.
En principio, podemos abrir una ventana de comando (Inicio / Ejecutar... cmd) y... y nada más. En Windows XP y Windows 7 la propia ventana ya te muestra una línea con la versión, aunque puede ser un poco críptico entender que la versión 6.1.7601 es en realidad Windows 7
Fig. 3. Tengo el Windows 6.1.7601. ¡Qué sorpresa!
No obstante, si queremos usar la información en un script, necesitaremos un comando que devuelva esa información. Como podéis ver en la Fig. 3, el comando ver permite obtener esta información.
Al menos Windows XP sí que te pone, antes del numerito, que estás utilizando Windows XP
Fig. 4. Y este es el XP
3. Linux, modo gráfico
Cada distro de Linux es un mundo, así que yo sólo puedo hablar de Ubuntu 15.04, que es lo que tengo actualmente. En ese caso, en la pantalla de login inicial se muestra la información:
Fig. 5. Información sobre la versión en Ubuntu 15.04, antes de entrar
4. Linux, modo ventana
Pero de nuevo, si nos interesa obtener la información en un comando para usar esto en nuestros scripts, podemos utilizar el comando lsb_release con el parámetro -a (lo de LSB significa Linux Standard Base, por si ardíais en deseos de saberlo, que os conozco)
Fig. 6. Comando lsb... (LSB = ¿Lo SaBe? ¡Vivan los chistes malos!)
Desconozco si este comando es el mismo en otras distros, aunque imagino (más bien, espero) que sí.
En cuanto al comando, me gusta más cómo lo hace Windows. Creo que "ver" es bastante intuitivo y fácil de recordar para recuperar la VERsión, mientras que el comando de Ubuntu no me parece tan recordable (entre otras, esa es una de las razones por las que escribo estas notas para mí). Sin embargo, en la información que devuelven, veo mucho más legible la de Ubuntu que la de Windows 7.
5. Android y similares
Ya puestos, pongamos también cómo consultarlo en Android, porque muchas veces las aplicaciones que podemos instalar están limitadas por la versión de Android, y aquellos usuarios para los cuáles yo soy su servicio-técnico-del-móvil con frecuencia no saben la versión de Android que lleva su móvil. Imagino que esto os pasará a más de uno.
Lo de "similares" que he puesto en el título de este apartado es que en mi caso, en vez de mirarlo en un Android "estándar" de Google, yo tengo el CyanogenMod, pero vamos, para el caso, es lo mismo.
Para ver la versión en estos SO, hay que entrar en Ajustes / Información del teléfono y buscar una entrada similar a esta
Fig. 7. Version de Android / Cyanogenmod
6. La anécdota
Y por último, y hablando de versiones de sistemas operativos, dejemos hueco para la anécdota. Como sabréis, tras el récord de permanencia de XP (mira que ha durado años en nuestros equipos: era una buena herramienta), las versiones de Windows se han sucedido en los últimos años a una velocidad algo rápida: Windows 7, Windows 8 y... ¿Windows 9? Pues no, directamente ahora llega Windows 10. Y, aunque no hay una explicación oficial para este salto, esta entrada de Genbetadev comenta algunas de las bromas que se han utilizado para explicar este hecho. Y después acaba mostrando código REAL que parece hecho de broma. Muy ameno, bien explicado y recomendable para quién tenga que programar y pelearse con la versión del sistema operativo.
jueves, 9 de julio de 2015
Generar RTF desde nuestras aplicaciones
A veces puede ser muy interesante que nuestra aplicación genere un fichero RTF que luego los usuarios puedan editar con Word o Writer para modificar, imprimir, convertir a diferentes formatos como PDF, docx, odt...
La buena noticia es que los RTF son simplemente ficheros de texto con unas etiquetas especiales que indican el formato del texto, de las tablas, de las imágenes y de los demás elementos. Así que no es difícil hacer un programa que vaya escribiendo este tipo de etiquetas combinadas con el texto a incluir.
La mala noticia es que los distintos editores con capacidad para crear un RTF tienen distintas opiniones acerca de lo que debe incluirse en un documento con Formato de Texto Enriquecido (que es lo que significa más o menos la sigla RTF, Rich Text Format).
Si creáis un RTF sencillo con cualquier editor ofimático, tendréis algo así (en este caso, parto de un RTF creado con LibreOffice Writer 4.4 en Ubuntu):
Y ahora, si en vez de hacer doble clic sobre el icono del fichero, lo abrís con un editor de texto podréis ver algo similar a esto:
Si abrimos ese mismo RTF con Word 2003 y lo volvemos a guardar, vemos que Word le ha metido bastante más información
Por último, lo he abierto y vuelto a guardar con WordPad (de Windows 7) y veo que es el que deja el RTF más limpito, con aparentemente la menor cantidad de información.
Como es lógico, los tres ficheros difieren bastante en el tamaño, ya que la versión de Word es la que más información lleva (8 KB) y la versión de WordPad es la más pequeña (225 bytes).
Como curiosidad, decir que he generado un RTF a mano con el editor de texto y dejándolo en algo tan reducido como esto
Aquí podéis ver los tamaños de las distintas versiones
Ojo, el caso manual tiene "trampa", pues me he saltado algunas partes que son necesarias según la especificación oficial del formato RTF, pero como los programas prefieren rellenar la falta de información con valores predefinidos antes que morir dando un error miserablemente, podemos abrir este documento hecho a mano sin problemas en Word 2003, WordPad y LibreOffice 4.3 (tanto versiones de Windows como de Ubuntu), que ya se encargan ellos de asignar valores por defecto a todo lo que no se especifique (fuentes de texto, colores...). Eso sí, cada uno de estos programas le ha puesto un tipo de letra y un tamaño a su antojo, ya que el documento creado de forma manual no indica nada respecto a las fuentes a utilizar, así que los valores por defecto juegan aquí un papel fundamental.
En próximas entradas entraré en los detalles de los RTFs, a fin de que nuestras aplicaciones puedan generar este tipo de ficheros sin demasiadas complicaciones.
Por de pronto, los impacientes pueden ir empezando a leerse la especificación oficial:
http://www.biblioscape.com/rtf15_spec.htm
Para mí ha sido la Biblia durante unos cuantos días.
La buena noticia es que los RTF son simplemente ficheros de texto con unas etiquetas especiales que indican el formato del texto, de las tablas, de las imágenes y de los demás elementos. Así que no es difícil hacer un programa que vaya escribiendo este tipo de etiquetas combinadas con el texto a incluir.
La mala noticia es que los distintos editores con capacidad para crear un RTF tienen distintas opiniones acerca de lo que debe incluirse en un documento con Formato de Texto Enriquecido (que es lo que significa más o menos la sigla RTF, Rich Text Format).
Si creáis un RTF sencillo con cualquier editor ofimático, tendréis algo así (en este caso, parto de un RTF creado con LibreOffice Writer 4.4 en Ubuntu):
Fig. 1. Un RTF sencillo
Y ahora, si en vez de hacer doble clic sobre el icono del fichero, lo abrís con un editor de texto podréis ver algo similar a esto:
Fig. 2. Las tripas del RTF (versión LibreOffice Writer)
Si abrimos ese mismo RTF con Word 2003 y lo volvemos a guardar, vemos que Word le ha metido bastante más información
Fig. 3. El RTF después de pasar por las manos de MS-Word, el cual ha decidido añadirle muuuuuuchas cosas
Por último, lo he abierto y vuelto a guardar con WordPad (de Windows 7) y veo que es el que deja el RTF más limpito, con aparentemente la menor cantidad de información.
Fig. 4. El RTF exportado con WordPad (Windows 7)
Como es lógico, los tres ficheros difieren bastante en el tamaño, ya que la versión de Word es la que más información lleva (8 KB) y la versión de WordPad es la más pequeña (225 bytes).
Como curiosidad, decir que he generado un RTF a mano con el editor de texto y dejándolo en algo tan reducido como esto
Fig. 5. Un RTF superreducido generado a mano
Aquí podéis ver los tamaños de las distintas versiones
Fig. 6. A menos paja, menos tamaño
Ojo, el caso manual tiene "trampa", pues me he saltado algunas partes que son necesarias según la especificación oficial del formato RTF, pero como los programas prefieren rellenar la falta de información con valores predefinidos antes que morir dando un error miserablemente, podemos abrir este documento hecho a mano sin problemas en Word 2003, WordPad y LibreOffice 4.3 (tanto versiones de Windows como de Ubuntu), que ya se encargan ellos de asignar valores por defecto a todo lo que no se especifique (fuentes de texto, colores...). Eso sí, cada uno de estos programas le ha puesto un tipo de letra y un tamaño a su antojo, ya que el documento creado de forma manual no indica nada respecto a las fuentes a utilizar, así que los valores por defecto juegan aquí un papel fundamental.
En próximas entradas entraré en los detalles de los RTFs, a fin de que nuestras aplicaciones puedan generar este tipo de ficheros sin demasiadas complicaciones.
Por de pronto, los impacientes pueden ir empezando a leerse la especificación oficial:
http://www.biblioscape.com/rtf15_spec.htm
Para mí ha sido la Biblia durante unos cuantos días.
miércoles, 24 de junio de 2015
Trocear parámetros de la línea de comando (comando xargs)
Hoy os voy a contar la solución a un pequeño problema que se me ha presentado hace unos días, y así aprovecho para contaros una cosa que no sabía y que he acabado utilizando del comando xargs.
El caso es que tenemos un script que procesa cadenas de texto y compone con ellas una cadena más grande. En concreto, las cadenas son una serie de valores con los que el script compone la condición de una instrucción SQL (una select) del estilo
select campo1, campo2...
from tabla
where dato in ('dato1', 'dato2', 'dato3'...)
Esos dato1, dato2... son los parámetros que se le pasan al script.
Queda más claro viendo la Fig. 1.
Como es fácil imaginar, el script no está pensado para ejecutarlo manualmente, sino que las cadenas a incluir proceden de una lista existente en un fichero de texto plano. He sustituido los datos reales por basura, pero más o menos, algo así:
Hay que aclarar que el script no procesa la entrada estándar, en cuyo caso podríamos haber utilizado los pipes (tuberías), sino que espera que le llegue la lista de cadenas (datos) como parámetros. Es decir, los extrae de la variable $argv (es un script PHP).
Una forma fácil de pasarle los valores al script podría ser utilizando las comillas simples invertidas para ejecutar el comando cat y luego la salida de este comando que se sustituya en la línea de comandos de la llamada a nuestro script. No os compliquéis leyendo de nuevo lo que he dicho, queda más claro leyendo el código de la Fig. 3. Vamos, algo así:
Otra solución podría ser utilizar el programa xargs. ¿Y qué hace este programa? Básicamente, recoge todo lo que haya en su entrada estándar y se lo pasa como parámetros al programa que le digamos. Se entenderá mejor con un ejemplo: vamos a ver en la Fig. 4 cómo conseguir lo que hemos hecho antes utilizando xargs en vez de las comillas invertidas.
Hasta aquí vemos dos formas en apariencia más o menos equivalentes (de momento, no entraremos a hablar de rendimiento) de hacer lo mismo. Sin embargo, el problema que estamos resolviendo tiene una peculiaridad más, y aquí ya veremos cómo ambas formas de hacerlo ya no nos valen por igual.
Y aquí es donde se revela una ventaja muy importante de xargs: la capacidad de generar no una, sino N llamadas al comando indicado, pero dándole "bloques" de argumentos del tamaño que queramos. Es decir, en vez de llamar una sola vez al script, y en esa llamada pasarle todos los parámetros de golpe, puede que queramos ir pasándole los argumentos de 10 en 10, pongamos por caso, y que nos devuelva las diferentes SQL con los parámetros de cada bloque.
¿Y cómo se consigue esto: simplemente con la opción -nX del comando xargs, donde debemos sustituir X por el número que indique cuántos parámetros se le pasarán al comando en cada llamada. Así, por ejemplo, si queremos pasarle los argumentos de 10 en 10, pondríamos lo siguiente:
En este caso, la lista que he utilizado tiene sólo 29 elementos, así que podemos ver que en la última SELECT se han utilizado los 9 últimos que quedaban, y no 10 argumentos, como en las dos llamadas anteriores. Es decir, que si el script está pensado para recibir un número fijo de parámetros, hay que tener en cuenta que al trocearlos, es posible que la última invocación no incluya todos los necesarios.
Una cosa interesante es que si invocáis a xargs con la opción -t, podéis ver qué se ejecutará sin llegar a ejecutarlo de verdad, sólo se muestra la línea de comando que se ejecutaría. Esto viene bien para hacer pruebas antes de lanzar la llamada definitiva.
No me extiendo más, pero os sugiero que le dediquéis un rato a la página del manual del comando xargs, que posiblemente amortizaréis el tiempo empleado en ello.
Que ustedes tengan un buen tecleo.
2. En inglés: https://en.wikipedia.org/wiki/Xargs
El caso es que tenemos un script que procesa cadenas de texto y compone con ellas una cadena más grande. En concreto, las cadenas son una serie de valores con los que el script compone la condición de una instrucción SQL (una select) del estilo
select campo1, campo2...
from tabla
where dato in ('dato1', 'dato2', 'dato3'...)
Esos dato1, dato2... son los parámetros que se le pasan al script.
Queda más claro viendo la Fig. 1.
Como es fácil imaginar, el script no está pensado para ejecutarlo manualmente, sino que las cadenas a incluir proceden de una lista existente en un fichero de texto plano. He sustituido los datos reales por basura, pero más o menos, algo así:
Fig. 2. La lista de valores a procesar. Imaginativa, ¿a que sí? Lo que yo decía...
Hay que aclarar que el script no procesa la entrada estándar, en cuyo caso podríamos haber utilizado los pipes (tuberías), sino que espera que le llegue la lista de cadenas (datos) como parámetros. Es decir, los extrae de la variable $argv (es un script PHP).
Una forma fácil de pasarle los valores al script podría ser utilizando las comillas simples invertidas para ejecutar el comando cat y luego la salida de este comando que se sustituya en la línea de comandos de la llamada a nuestro script. No os compliquéis leyendo de nuevo lo que he dicho, queda más claro leyendo el código de la Fig. 3. Vamos, algo así:
Fig. 3. Uso de las comillas simples invertidas para pasar los parámetros al script
Otra solución podría ser utilizar el programa xargs. ¿Y qué hace este programa? Básicamente, recoge todo lo que haya en su entrada estándar y se lo pasa como parámetros al programa que le digamos. Se entenderá mejor con un ejemplo: vamos a ver en la Fig. 4 cómo conseguir lo que hemos hecho antes utilizando xargs en vez de las comillas invertidas.
Fig. 4. Uso de xargs para conseguir el mismo resultado que antes
Hasta aquí vemos dos formas en apariencia más o menos equivalentes (de momento, no entraremos a hablar de rendimiento) de hacer lo mismo. Sin embargo, el problema que estamos resolviendo tiene una peculiaridad más, y aquí ya veremos cómo ambas formas de hacerlo ya no nos valen por igual.
TROCEAR LA ENTRADA
La lista a procesar tiene muuuuuuuuuuchos valores, más de diez mil. En vez de que se nos genere una cláusula "in" monstruosamente grande, lo que queremos es trocear la consulta en diferentes consultas que iremos dosificando poco a poco a la base de datos, a fin de no saturarla y poder ir obteniendo resultados parciales. O por los motivos que sea, que ahora mismo dan igual.Y aquí es donde se revela una ventaja muy importante de xargs: la capacidad de generar no una, sino N llamadas al comando indicado, pero dándole "bloques" de argumentos del tamaño que queramos. Es decir, en vez de llamar una sola vez al script, y en esa llamada pasarle todos los parámetros de golpe, puede que queramos ir pasándole los argumentos de 10 en 10, pongamos por caso, y que nos devuelva las diferentes SQL con los parámetros de cada bloque.
¿Y cómo se consigue esto: simplemente con la opción -nX del comando xargs, donde debemos sustituir X por el número que indique cuántos parámetros se le pasarán al comando en cada llamada. Así, por ejemplo, si queremos pasarle los argumentos de 10 en 10, pondríamos lo siguiente:
Fig. 5. Pasando los parámetros al script en bloques de 10
En este caso, la lista que he utilizado tiene sólo 29 elementos, así que podemos ver que en la última SELECT se han utilizado los 9 últimos que quedaban, y no 10 argumentos, como en las dos llamadas anteriores. Es decir, que si el script está pensado para recibir un número fijo de parámetros, hay que tener en cuenta que al trocearlos, es posible que la última invocación no incluya todos los necesarios.
Una cosa interesante es que si invocáis a xargs con la opción -t, podéis ver qué se ejecutará sin llegar a ejecutarlo de verdad, sólo se muestra la línea de comando que se ejecutaría. Esto viene bien para hacer pruebas antes de lanzar la llamada definitiva.
No me extiendo más, pero os sugiero que le dediquéis un rato a la página del manual del comando xargs, que posiblemente amortizaréis el tiempo empleado en ello.
Que ustedes tengan un buen tecleo.
PARA SABER MÁS
1. En español: http://systemadmin.es/2009/04/uso-de-xargs-herramientas-unix-ii#2. En inglés: https://en.wikipedia.org/wiki/Xargs
viernes, 12 de junio de 2015
Segundo portlet con Liferay: listar una tabla (parte 2 de 2)
Bueno, por diversos motivos he tenido que estar parado un tiempo sin poder actualizar el blog, lo siento mucho. Así que voy a ver si ahora puedo poco a poco volver a la normalidad y hacer las entradas de forma más frecuente.
Continuamos con la creación de un portlet que consulta a una BD Oracle y nos muestra los datos en una simple tabla HTML.
Enlace a la primera parte.
Recordemos que lo último que habíamos hecho era incluir el driver de Oracle en nuestro proyecto, así que ya podemos pasar a establecer la conexión con la BD.
import java.sql.Connection;
...
//conectar
Connection conOracle = null;
conOracle = this.getConexionOracle();
También necesitaremos otras clases de este paquete, así que las añadiremos:
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
Una opción más cómoda sería haber importado todo el paquete java.sql con una única instrucción, así:
import java.sql.*;
Pero yo prefiero especificar individualmente cada clase (si fueran muchísimas no me complicaría la vida e importaría todo el paquete, pero en este caso son pocas). De esta manera, hacemos explícito el conocimiento de las clases que estamos importando.
Para conectar con un servidor Oracle, necesitamos los siguientes datos: servidor (nombre o dirección IP), puerto (por defecto, 1521), nombre del esquema, usuario y la clave. Si tenéis claro todo esto, el método para obtener la conexión quedaría algo así (he borrado los datos específicos de mi instalación, naturalmente):
private Connection getConexionOracle() {
String
servidor = "xx",
puerto = "1521",
esquema = "xx",
passBD = "xx",
usuario = "xx";
String cadenaBD = "jdbc:oracle:thin:@" + servidor + ":" + puerto + ":" + esquema;
Connection conOracle = null;
try {
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
conOracle = java.sql.DriverManager.getConnection(cadenaBD, usuario, passBD);
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Error en getConexionOracle() : " + e.getMessage());
}
return conOracle;
}
OJO: esto de poner en el propio código Java los datos de la conexión probablemente no es la forma más adecuada de hacerlo. De momento lo dejaremos así por simplicidad de comprensión, pero no es lo más recomendable. Sería mejor configurar la conexión a nivel del contenedor de portlets (Tomcat en nuestro caso, Javaboss... ) y desde el código Java obtener la conexión.
//recuperar datos
Statement orclStmt = conOracle.createStatement();
String sql = "select campo1, campo2 from tabla order by campo1 ";
orclResult = orclStmt.executeQuery(sql);
Como vemos, se utiliza el método createStatement del objeto conOracle y el objeto Statement devuelto nos permite ejecutar la consulta correspondiente.
El objeto oraclResult es de tipo java.sql.ResultSet. Como véis, no lo he declarado en estas líneas, y eso se debe a que voy a poner todo este código dentro de un bucle try/catch, ya que los métodos createStatement y executeQuery pueden lanzar algunas excepciones y debemos atraparlas. Por ello, declararé las variables orclResult y la variable conOracle antes de este bloque, así:
public String recuperarTablaHTML() {
String res = "<table border=1>";
Connection conOracle = null;
ResultSet orclResult = null;
try {
//conectar
conOracle = this.getConexionOracle();
//recuperar datos
Statement orclStmt = conOracle.createStatement();
String sql = "select campo1, campo2 from tabla1 order by campo1 ";
orclResult = orclStmt.executeQuery(sql);
Nuestro código va tomando forma.
while (orclResult.next()) {
String campo1 = orclResult.getString("campo1");
String campo2 = orclResult.getString("campo2");
res += "<tr>";
res += "<td>" + campo1 + "</td>";
res += "<td>" + campo2 + "</td>";
res += "</tr>";
this.numResultados++;
}
También hemos introducido en el bucle un contador del número de registros procesados, como puede verse en la última línea dentro del bucle.
Ahora nos vamos al portal y comprobamos si todo funciona como debería:
Bueno, parece que sí. Así que ya podemos dar por terminada esta entrada.
Continuamos con la creación de un portlet que consulta a una BD Oracle y nos muestra los datos en una simple tabla HTML.
Enlace a la primera parte.
Recordemos que lo último que habíamos hecho era incluir el driver de Oracle en nuestro proyecto, así que ya podemos pasar a establecer la conexión con la BD.
5. Establecer la conexión
Para crear la conexión, necesitamos un objeto de la clase Connection. Esta clase se encuentra en el paquete java.sql, así que añadiremos estas líneas al código:import java.sql.Connection;
...
//conectar
Connection conOracle = null;
conOracle = this.getConexionOracle();
También necesitaremos otras clases de este paquete, así que las añadiremos:
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
Una opción más cómoda sería haber importado todo el paquete java.sql con una única instrucción, así:
import java.sql.*;
Pero yo prefiero especificar individualmente cada clase (si fueran muchísimas no me complicaría la vida e importaría todo el paquete, pero en este caso son pocas). De esta manera, hacemos explícito el conocimiento de las clases que estamos importando.
Para conectar con un servidor Oracle, necesitamos los siguientes datos: servidor (nombre o dirección IP), puerto (por defecto, 1521), nombre del esquema, usuario y la clave. Si tenéis claro todo esto, el método para obtener la conexión quedaría algo así (he borrado los datos específicos de mi instalación, naturalmente):
private Connection getConexionOracle() {
String
servidor = "xx",
puerto = "1521",
esquema = "xx",
passBD = "xx",
usuario = "xx";
String cadenaBD = "jdbc:oracle:thin:@" + servidor + ":" + puerto + ":" + esquema;
Connection conOracle = null;
try {
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
conOracle = java.sql.DriverManager.getConnection(cadenaBD, usuario, passBD);
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Error en getConexionOracle() : " + e.getMessage());
}
return conOracle;
}
OJO: esto de poner en el propio código Java los datos de la conexión probablemente no es la forma más adecuada de hacerlo. De momento lo dejaremos así por simplicidad de comprensión, pero no es lo más recomendable. Sería mejor configurar la conexión a nivel del contenedor de portlets (Tomcat en nuestro caso, Javaboss... ) y desde el código Java obtener la conexión.
6. Realizar la consulta
Una vez obtenida la conexión, ya está hecho lo más difícil. Ahora tan sólo nos queda realizar la consulta, lo cual podemos hacer con el código que se ve a continuación//recuperar datos
Statement orclStmt = conOracle.createStatement();
String sql = "select campo1, campo2 from tabla order by campo1 ";
orclResult = orclStmt.executeQuery(sql);
Como vemos, se utiliza el método createStatement del objeto conOracle y el objeto Statement devuelto nos permite ejecutar la consulta correspondiente.
El objeto oraclResult es de tipo java.sql.ResultSet. Como véis, no lo he declarado en estas líneas, y eso se debe a que voy a poner todo este código dentro de un bucle try/catch, ya que los métodos createStatement y executeQuery pueden lanzar algunas excepciones y debemos atraparlas. Por ello, declararé las variables orclResult y la variable conOracle antes de este bloque, así:
public String recuperarTablaHTML() {
String res = "<table border=1>";
Connection conOracle = null;
ResultSet orclResult = null;
try {
//conectar
conOracle = this.getConexionOracle();
//recuperar datos
Statement orclStmt = conOracle.createStatement();
String sql = "select campo1, campo2 from tabla1 order by campo1 ";
orclResult = orclStmt.executeQuery(sql);
Nuestro código va tomando forma.
7. El bucle de procesamiento
Una vez obtenido el resultado, ya sólo nos queda ir recorriendo el conjunto de registros del resultado. Algo que podemos hacer así:while (orclResult.next()) {
String campo1 = orclResult.getString("campo1");
String campo2 = orclResult.getString("campo2");
res += "<tr>";
res += "<td>" + campo1 + "</td>";
res += "<td>" + campo2 + "</td>";
res += "</tr>";
this.numResultados++;
}
También hemos introducido en el bucle un contador del número de registros procesados, como puede verse en la última línea dentro del bucle.
8. Mostrar los resultados
Bueno, pues hecho todo lo anterior, sólo nos queda regresar al fichero view.jsp y añadir el código para mostrar el resultado.
Fig. 17. Mostrando los resultados en la vista del portlet
Ahora nos vamos al portal y comprobamos si todo funciona como debería:
Fig. 18. Ejecutando el portlet en nuestro portal
Bueno, parece que sí. Así que ya podemos dar por terminada esta entrada.
Suscribirse a:
Entradas (Atom)