jueves, 13 de junio de 2013

Comprimir y Descomprimir archivos en formato ZIP [JAVA]


Antes de empezar es bueno incluir un poco de información acerca del formato ZIP:

En informáticaZIP o zip es un formato de almacenamiento sin pérdida, muy utilizado para la compresión de datos como documentos, imágenes o programas.Para este tipo de archivos se utiliza generalmente la extensión ".zip".Muchos programas, tanto comerciales como libres, lo utilizan y permiten su uso más habitual.

Considero que junto a el formato rar, son los formatos de compresión de archivos más utilizados. La máquina virtual de Java nos permite el manejo de este tipo de archivos. Con una clase que contenga los métodos de compresión / descompresión  podemos realizar fácilmente una aplicación portable y ligera que realice la compresión y descompresión de archivos desde nuestra memoria USB.

A continuación podemos ver el código para manejar archivos .ZIP

//Primero importar librerias para manejo de archivos y archivos zip
import java.util.zip.*;

import java.io.*;

public class ZIP {

private static final int BUFFER_SIZE = 1024;

        public void Comprimir(String archivoOriginal, String archivoZIP) throws Exception {
// bjetos en memoria
FileInputStream archivoEntrada = null;
FileOutputStream archivoSalida = null;
ZipOutputStream zipos = null;

// buffer
byte[] buffer = new byte[BUFFER_SIZE];
try {
// fichero entrada
archivoEntrada = new FileInputStream(archivoOriginal);
archivoSalida = new FileOutputStream(archivoZIP);
// fichero comprimido
zipos = new ZipOutputStream( archivoSalida);
ZipEntry zipEntry = new ZipEntry(archivoOriginal);
zipos.putNextEntry(zipEntry);
int len = 0;
// zippear
while ((len = archivoEntrada.read(buffer, 0, BUFFER_SIZE)) != -1)
zipos.write(buffer, 0, len);
// volcar la memoria al disco
zipos.flush();
} catch (Exception e) {
throw e;
} finally {
// cerramos los archivos
zipos.close();
archivoEntrada.close();
archivoSalida.close();
} // cerramos try.
} // cerramos Comprimir

public void Descomprimir(String archivoZIP, String archivoDescomprimido) throws Exception {
BufferedOutputStream bos = null;
FileInputStream fis = null;
ZipInputStream zipis = null;
FileOutputStream fos = null;

try {
fis = new FileInputStream(archivoZIP);
zipis = new ZipInputStream(new BufferedInputStream(fis));
if (zipis.getNextEntry() != null) {
int len = 0;
byte[] buffer = new byte[BUFFER_SIZE];
fos = new FileOutputStream(archivoDescomprimido);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);

while  ((len = zipis.read(buffer, 0, BUFFER_SIZE)) != -1)
bos.write(buffer, 0, len);
bos.flush();
} else {
throw new Exception("Zip Vacio");
} // cierra if
} catch (Exception e) {
throw e;
} finally {
bos.close();
zipis.close();
fos.close();
fis.close();
} // cierra try

} // cierra descomprimir

Debemos entender que al comprimir ingresamos la ruta del archivo a comprimir como primer parámetro y la ruta del fichero resultante como segundo parámetro. En descomprimir es el orden contrario. Espero haber escrito las variables de manera entendible.

Para probar el código podemos crear una nueva Main Class o agregar esto al final.

                        ZIP archivo = new ZIP();
                        String archivoEntrada="imagen.jpg";//ruta del fichero original 
                        String archivoSalida="imagen.zip";//ruta del fichero generado
archivo.Comprimir(archivoEntrada, archivoSalida);
System.out.println("Comprimido en zip!");
                        archivoEntrada="imagen.zip";//ruta del fichero original 
                        archivoSalida="imagen2.jpg";//ruta del fichero generado
archivo.Descomprimir(archivoEntrada, archivoSalida);
System.out.println("ZIP Descomprimido!");

El texto resaltado corresponde a las rutas usadas para probar el programa. Debes colocar una imagen.jpg en tu proyecto al mismo nivel que la carpeta src o simplemente prueba con cualquier otra ruta.

Próximamente actualizaré la publicación compartiendo una aplicación gráfica que comprima y descomprima los archivos ZIP.

martes, 11 de junio de 2013

Aplicación Java para realizar Capturas de Pantalla


El día de hoy se me ocurrió realizar una aplicación que realizara capturas de pantalla, o impresiones de pantalla y que las exportara a un archivo de imagen jpg, png, gif, bmp, etc

Investigando un poco encontré información acerca de la clase Robot y entre otras cosas  la clase nos permite realizar capturas de nuestra pantalla con gran nitidez(también depende del tipo de imagen generado).



No me extenderé tratando de explicar cada formato de imagen porque no es el objetivo de mi publicación. Pueden jugar con el código y experimentar, para así sacar sus propias conclusiones.

Este es el ejemplo más sencillo para hacer una captura de la pantalla completa.

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;

class CapturarPantalla {
  public static void main(String args[])
        throws AWTException, IOException {
     // captura la pantalla completa
     BufferedImage pantalla = new Robot().createScreenCapture(
     new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );//se obtiene el tamaño de la pantalla
     
     // Lo guarda como un png, podemos modificarlo y guardarlo como jpg,gif,bmp
     File file = new File("pantalla.png");//creamos el archivo
     ImageIO.write(pantalla, "png", file);//escribimos la imagen en archivo   
   }
}


Como podrán observar el código es muy simple. La linea resaltada en rojo corresponde el lugar donde se guardara el archivo. En este caso se crea en la carpeta principal del proyecto. Es posible escribir cualquier ubicación válida, por ejemplo "d:/pantalla.png", "c:/capturas/pantalla.png", etc.

Si deseamos conocer los formatos de imagen disponibles podemos mostrarlos con el siguiente código.
String writerNames[] = ImageIO.getWriterFormatNames();
     for(String aux:writerNames){
         System.out.println(aux);
     }

Parece una forma muy simple de realizar capturas de pantalla. Pero lo más útil sería que fuera una interfaz gráfica la que te ayudara a realizar esta función. Todo depende de la creatividad e imaginación del programador.

Mi aplicación.
En mi caso las interfaces gráficas no son lo mio, realice una aplicación sencilla que nos permite fácilmente capturar la pantalla o parte de ella y almacenarla en un archivo en múltiples formatos. El único formato que al parecer no me funciono fue wbmp,WBMP

La app tiene un tamaño de 83.4 kb y puedes guardarla en tu memoria usb.

Al posicionar el cursor sobre los elementos de la aplicación podemos obtener la descripción de sus funciones.

¿Como funciona?
1.-El funcionamiento es muy sencillo, el botón con el icono realiza la captura de pantalla.
2.-Puedes elegir 2 tipos de capturas:
    a)Pantalla completa: Como su nombre lo dice captura toda la pantalla.
    b)Seleccionado: Captura el área seleccionada. ¿Como seleccionar? Cuando se elige "Seleccionado" la ventana permite ser re dimensionada y sirve para capturar el área cubierta por la ventana de la aplicación.

3.-Tipo de Imagen: Selecciona el formato para exportar la imagen. Puede ser jpg, jpeg,gif,png . La opción predeterminada es png ya que genera imágenes más claras.

4.- Delay(segundos):  Es el tiempo que debe pasar entre ocultar la ventana de aplicación y realizar la captura. Evita que se incluya la ventana de aplicación en la captura. En caso de que aparezcan restos de la ventana se debe aumentar el valor. Si quiere incluir la ventana de la aplicación en la imagen seleccione 0.

5.-Guardar en: Su función es elegir la carpeta donde se guarda la imagen. Si no lo define se mostrará Ubicación de la aplicación. Esto quiere decir que la captura se almacenara en la carpeta donde se ubica la aplicación y se nombrara como captura_11062013_22-58-27.png  donde los números significan día,mes, año_hora-minuto-segundo

6.-Abrir imagen creada. Esta opción permite que después de generado el archivo se muestre con el visor de imágenes. Si marca la opción se mostrará la imagen, de lo contrario no.



Si deseas probar la aplicación puedes descargarla .

MEGA Screen.rar (54 KB)
DropBox Screen.rar(54 KB)
Box Screen.rar(54 KB)




martes, 4 de junio de 2013

Java Mail (Parte4) Obtener mensajes no leídos de GMail y Yahoo Mail [IMAP]

El envío de mensajes a través de JavaMail es un proceso de baja complejidad comparado con la lectura de los mensajes de nuestra bandeja de entrada.
La complejidad es causada porque cuando nosotros enviamos en mensaje especificamos que elementos contiene el cuerpo del mensaje, cuando intentamos leer los mensajes esto es un problema. No sabemos con certeza si el mensaje solo contiene texto, si esta en formato HTML, si contiene uno o mas adjuntos y que tipo de archivos están adjuntados(imágenes, documentos, archivos comprimidos, audio,video,etc)

A continuación presento en código fuente de una clase Java que obtiene los mensajes sin leer de nuestra cuenta de GMail ó Yahoo. Sólo se muestra el texto de los mensajes, en caso de que el mensaje contenga adjuntos no mostrará nada.

Este código es una modificación del que se encuentra en aqui. Para que la aplicación funcione correctamente es necesario importar las librerías  disponibles en este post

Aclaro que este ejemplo solo muestra los mensajes de tipo texto, si contiene imágenes o archivos adjuntos no se mostrará.

import java.util.Properties;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FlagTerm;

public class EmailReader {

    public static void main(String args[]) {
        Properties props = System.getProperties();
        props.setProperty("mail.store.protocol", "imaps");
        try {
                Session session = Session.getDefaultInstance(props, null);
                Store store = session.getStore("imaps");

                // servidor IMAP para gmail. 
                // remplazar <usuario> con su usuario de Gmail.
                // remplazar <password> con el password correspondiente al usuario especificado.

                store.connect("imap.gmail.com", "usuario@gmail.com", "password");

                // Servidor IMAP para yahoo.
                //store.connect("imap.mail.yahoo.com", "<username>", "<password>");

                System.out.println(store);

                Folder inbox = store.getFolder("Inbox");
                inbox.open(Folder.READ_ONLY);
                mostrarCorreosNoLeidos(inbox);//indicamos que lee los mails no leidos
                   
                
        } catch (NoSuchProviderException e) {
            System.out.println(e.toString());
            System.exit(1);
        } catch (MessagingException e) {
            System.out.println(e.toString());
            System.exit(2);
        }

    }
    
    static public void mostrarCorreosNoLeidos(Folder inbox){        
        try {
            FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
            Message msg[] = inbox.search(ft);
            System.out.println("Correos sin leer: "+msg.length);
            for(Message message:msg) {
                try {
                    System.out.println("Fecha: "+message.getSentDate().toString());
                    System.out.println("De: "+message.getFrom()[0].toString());            
                    System.out.println("Asunto: "+message.getSubject().toString());
                    System.out.println("Contenido: "+message.getContent().toString());
                    System.out.println("******************************************");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    System.out.println("Sin Información");
                }
            }
        } catch (MessagingException e) {
            System.out.println(e.toString());
        }
    }
}


------------------------------------------------------------------------------------------------------------
Por el momento sigo tratando de entender la estructura de los mensajes para poder leer mensajes complejos en formato HTML y con Archivos adjuntos, espero publicar una entrada en la que explique como realizar la lectura de mensajes complejos.