Mostrando las entradas con la etiqueta java. Mostrar todas las entradas
Mostrando las entradas con la etiqueta java. Mostrar todas las entradas

sábado, 7 de junio de 2014

Tutorial JNI en Linux parte 1

Este es el primer tutorial de JNI este tutorial forma parte de los de Java solo que es aparte ya que si los escribiera hasta que alcanzáramos este "nivel" de programación seria tardado ya que es de nivel avanzado y en los tutoriales de Java vamos en el 9 de nivel básico,faltarían 11 para entrar en este tema,así que lo veremos de una vez.

Bien primero que es JNI:

JNI son las siglas de de Java Native Interface, JNI es un framework con el cual podemos ejecutar métodos nativos(escritos en C,C++ y assembler),en la maquina virtual de Java,esto hace que podamos usar  soluciones de bajo nivel en un programa Java,la JNI se usa para ejecutar código mas veloz que el que este ejecuta en su maquina virtual.

Una consideración de JNI,ademas de otras que existen es que si implementamos métodos nativos Java pierde su "encanto" de que se puede portar donde sea,ya que si abran trabajado con C,C++ sabrán que los programas se hacen específicos para las distintas arquitecturas.

Una cosa buena de JNI es que al aprender a usarlo también nos servirá con Android cuando usemos el NDK.

Antes de empezar,este espacio de trabajo usare:

Sistema : Ubuntu 14.04 o Gentoo

Java version 8 : java version "1.8.0_05"

Editor de texto : Vim

Lenguaje de soporte : C

Compilador : gcc

Depurador : gdb

Terminal : gnome-terminal o konsole

Tutorial

Primero que nada vamos a crear una clase java que implemente un metodo nativo,vamos a hacer el ejemplo de Hola Mundo con JNI,para ello debemos implementar una función nativa en la clase la cual lleva dos modificadores  el tipo de funcion y no lleva implementacion,puede lucir asi:
private native void saluda();

El modificador private se usa porque se manipulara desde la propia clase solamente y en inversa el método nativo podrá acceder a elementos de la clase.

native es la palabra reservada para saber que sera un método nativo.

void es el tipo de función o de retorno,en este caso seria un procedimiento al no regresar nada.

saluda() es el nombre del procedimiento y en este caso no lleva parámetros.

Tenemos que hacer una cosa mas,tenemos que cargar la librería nativa,esto lo hacemos llamando la librería .so,que seria por ejemplo libHolaMundo.so, lo hacemos usando el bloque estático static que como mencionamos alguna vez este bloque se carga antes de cualquier cosa,dentro de el usamos la función System.loadLibrary le pasamos como argumento un String con el nombre de la librería sin lib y sin .so:

Por ejemplo:

System.loadLibrary("HolaMundo");

Bien así se ve el código entero:


// Archivo HolaMundo.java

class HolaMundo {
    private native void saluda();
    static {
        System.loadLibrary("HolaMundo");
    }
    
    public static void main(String []args) {
        System.out.println("Hola desde Java");
        new HolaMundo().saluda();
    }
    
}

Ahora debemos compilarlo:

javac HolaMundo.java

Esto nos genera el .class,aun no lo podemos ejecutar ya que necesitamos la librería,lo que debemos hacer es crearla,para ello debemos compilar un .c como .so,pero primero necesitamos crearlo y para ello primero debemos crear una cabecera .h,lo bueno es que java tiene esta utilidad:

Creamos el header:

javah HolaMundo


Ahora bien nos genera el .h y aunque es muy importante no debemos editarlo,incluso nos lo advierten en la primera linea:

Lo que debemos de ver es la funcion que crea,ya que es la que debemos implementar en el .c del mismo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <jni.h>
/* Header for class HolaMundo */

#ifndef _Included_HolaMundo
#define _Included_HolaMundo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HolaMundo
 * Method:    saluda
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HolaMundo_saluda
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

En este caso:

JNIEXPORT void JNICALL Java_HolaMundo_saluda  (JNIEnv *, jobject);
Como vemos contiene dos Macros:

JNIEXPORT y JNICALL,los cuales se encargan de ejecutar correctamente la función.

Cambien tenemos el tipo de función en este caso void,como es un tipo similar al de c no hay problema ,pero veremos otros si fuera por ejemplo una función int,veríamos un jint,o una función String veríamos un jstring,etc.

Vemos el nombre de la función dividido en tres partes:

Java, el nombre de la clase y el nombre de la función escrita en la clase.

Por ultimo vemos dos argumentos?

Pero porque dos argumentos si no le pasamos nada desde java,estos son un JNIEnv que es el entorno,el que usaremos para toda la manipulación de datos de java,y un jobject que es la representación de la clase misma de Java(la que llama al programa en C).

Bien ahora si vamos a crear el .c,el cual no hará casi nada solo implementar esa función:

En la primera linea debemos o deberíamos llamar a jni.h pero como ya lo llamamos en el HolaMundo.h no es necesario,aunque podemos hacerlo,luego incluimos el stdio.h como siempre y por ultimo creamos la función que nos muestra el .h,prácticamente podemos copiar y pegar,pero no ya que aunque el .h define los dos argumentos que vamos usar no define los nombres,así queda el .c:


1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "HolaMundo.h"


JNIEXPORT void JNICALL Java_HolaMundo_saluda
  (JNIEnv * env, jobject obj)
{
    puts("Hola desde JNI");
}

Bien ahora solo queda crear el .so,para ello debemos compilar llamando las librerias necesarias,en mi caso(por la versión de java que uso):

gcc -shared -I/usr/lib/jvm/java-8-oracle/include/ -I/usr/lib/jvm/java-8-oracle/include/linux/ -o libHolaMundo.so HolaMundo.c -Wall

Lo que esta en rojo es lo que debemos cambiar(o tal vez no):

Eso es todo ahora basta ejecutar,pero debemos redefinir o agrear el PATH actual al  LD_LIBRARY_PATH,para que podamos usar la librería que acabamos de crear ya que actualmente esta en . y no donde java lo pide :

export LD_LIBRARY_PATH=.
Ejecutamos;

java HolaMundo




Si deseamos modificar un archivo debemos ejecutar todo de nuevo,el javac,el javah,el gcc así que podemos crear un script en bash para automatizarlo,bueno eso me sirve a mi,vean este seria:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
NAME=HolaMundo # Editar

PJAVA=java-8-oracle # Editar

function genera(){
echo "Ejecutando javac $NAME.java"

javac $NAME.java

echo "Ejecutando javah $NAME"

javah $NAME
}

function compila() {
echo "Ejecutando gcc"

gcc -shared -I/usr/lib/jvm/$PJAVA/include/ -I/usr/lib/jvm/$PJAVA/include/linux/ -o lib$NAME.so $NAME.c -Wall

}

function ejecuta() {
echo -e "Ejecutando $NAME\n"

java $NAME
}

function ayuda() {
echo "$0
         -h : ayuda
         -g : generar .h
         -e : ejecutar
         -c : compila
         -a : ejecutar todo
    "
}

case $1 in
    -e)
        ejecuta
    ;;
    -g)
        genera
    ;;
    -c)
        compila
    ;;
    -a)
        genera
        compila
        ejecuta
    ;;
    -h|"")
        ayuda
    ;;
esac

Así solo ejecutamos:

bash exec.sh -a


Todo lo que acabamos de hacer,crear el .java el .h,el .c,el .sh(opcional) siempre lo vamos a hacer,así que esa era la introducción a JNI,ahora lo que sigue es saber usar el API,manejar funciones y tipos de datos de jni.h,usar,obtener,devolver y modificar objetos de java desde el código .c.

Vamos a hacer una función saludar mejorada esta función saludara a un nombre que le pasemos,para eso modificamos la función de la clase HolaMundo.java para que quede así:

private native void saluda(String nombre);

También modificamos la llamada,que esta mas abajo:


new HolaMundo().saluda("nombre");


Ahora compilamos y generamos el .h:

bash exec.sh -g

o

javac HolaMundo.java

javah HolaMundo

Bien luego debemos editar el .c,ya que si vemos el .h,cambio y nos pasa un argumento mas:

jstring

Para usar la String que nos pasa Java debemos crear una referencia a un tipo const char, y luego apuntar al String,primero seria así:

const char * nombre;

Luego tenemos que pedir la String con la función GetStringUTFChars o GetStringChars de jni la cual nos devuelve el String en UTF-8 o Unicode,le pasamos tres argumentos,el primero es el entorno,el segundo es el jstring y el ultimo un jboolean,este no nos interesa,podemos ponerlo en NULL o en JNI_TRUE.

Para llamar una función de JNI usamos un puntero de env simulando una clase de C++,así:

(env*)->funcion

Así es como quedaría:

nombre = (*env)->GetStringUTFChars(env,name,NULL);

name es el nombre del parámetro jstring,no del nombre del const char.

Ya se podria usar este código,pero tenemos que seguir las normas de todo programador C, ver si se creo el puntero(si no es igual a NULL) y liberar la memoria del puntero.

Lo primero es fácil:

if (nombre == NULL) {
       return; // Terminamos la funcion
}

Lo segundo se logra con una funcion propia de la API,no es simplemente usar free(),esa funcion es:

ReleaseStringUTFChars o ReleaseStringChars dependiendo con cual creamos el puntero.

Le posamos tres argumentos,el entorno,el jstring y el puntero a jstring,el const char,en este caso:

(*env)->ReleaseStringUTFChars(env,name,nombre);

Eso es todo,asi queda el código completo:





1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include "HolaMundo.h"

JNIEXPORT void JNICALL Java_HolaMundo_saluda
  (JNIEnv * env, jobject obj,jstring name)
{
    const char *nombre;
    nombre = (*env)->GetStringUTFChars(env,name,NULL);
    if (nombre == NULL)
    {
        return;
    }

    printf("Hola desde JNI : %s\n",nombre);

    (*env)->ReleaseStringUTFChars(env,name,nombre);
    
}

Compilamos:

gcc -shared -I/usr/lib/jvm/$PJAVA/include/ -I/usr/lib/jvm/$PJAVA/include/linux/ -o lib$NAME.so $NAME.c -Wall

o

bash exec.sh -c

Y ejecutamos:

java HolaMundo

o

bash exec.sh -e


Por ultimo vamos a ver como podriamos retornar una String,supongamos que queremos hacer un algoritmo en C que cambie las palabras del string por el simbolo que sigue,esto es facil en C,luego lo retormamos y lo imprimimos en Java:

Así queda la clase Java:




1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Archivo : HolaMundo.java

class HolaMundo {
    private native void saluda(String nombre);
    private native String encripta(String palabra);
    static {
        System.loadLibrary("HolaMundo");
    }
    
    public static void main(String []args) {
        System.out.println("Hola desde Java");
        new HolaMundo().saluda("Atheyus");
        System.out.println(new HolaMundo().encripta("Tiempo de Tux"));
    }
    
}

Compilamos y generamos el .h:

bash exec.sh -g
El HolaMundo.h luce asi en estos momentos:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HolaMundo */

#ifndef _Included_HolaMundo
#define _Included_HolaMundo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HolaMundo
 * Method:    saluda
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_HolaMundo_saluda
  (JNIEnv *, jobject, jstring);

/*
 * Class:     HolaMundo
 * Method:    encripta
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_HolaMundo_encripta
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

Lo implementamos en el .c,así queda:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>
#include <string.h>
#include "HolaMundo.h"

JNIEXPORT void JNICALL Java_HolaMundo_saluda
  (JNIEnv * env, jobject obj,jstring name)
{
    const char *nombre;
    nombre = (*env)->GetStringUTFChars(env,name,NULL);
    if (nombre == NULL)
    {
        return;
    }

    printf("Hola desde JNI : %s\n",nombre);

    (*env)->ReleaseStringUTFChars(env,name,nombre);
}

JNIEXPORT jstring JNICALL Java_HolaMundo_encripta
  (JNIEnv * env, jobject obj, jstring word)
{
    const char *nombre;
    nombre = (*env)->GetStringUTFChars(env,word,NULL);
    if (nombre == NULL)
    {
        return NULL;
    }
    int size = (*env)->GetStringUTFLength(env,word);
    char encripta[size];
    char tnombre[size];
    strcpy(tnombre,nombre);
    int i;
    for (i=0;i<size;i++)
        encripta[i] = (tnombre[i]+1);
    jstring word_en = (*env)->NewStringUTF(env,encripta);
    (*env)->ReleaseStringUTFChars(env,word,nombre);
    return word_en;
}

Eso es todo compilamos y ejecutamos:


Para lograr eso en Java usaríamos StringBuilder,u otra opción pesada,pero en C asi seria,muy veloz,no voy a explicar las funciones dejo la documentación de ellas y de otras mas en el enlace que sigue:

Enlace
Leer más...

jueves, 5 de junio de 2014

Tutorial Java en Linux Basico 9

Interfaces

Antes que comenzar con la entrada,quiero mencionar que ya no había hecho entradas desde hace mucho tiempo por distintas razones,espero que ya pueda volver a escribir entradas,tutoriales con la recurrencia de antes.

Bien en este caso veremos la interfaces de java,no son interfaces gráficas(GUI) si no una implementacion de un tipo del propio lenguaje,así que esta entrada no esta relacionada con las interfaces graficas como Gtk,AWT,etc.

Una interfaz es algo muy raro en Java,mas si tienen como base o vienen de lenguajes como Python,Ruby o Perl,si vienen de C o C++,podríamos decir que es como una cabecera de archivo,pero tampoco,así que olviden lo que saben de esos lenguajes y háganse una idea nueva de esta forma de programar.

Las interfaces en Java sirven para varias cosas,unas de ellas son:

Polimorfismo.

Programación en equipo : Uso de plantillas.

Abstracción.

Herencia: Mas o menos.

Primero que nada debe quedar claro que una interfaz es una clase que no hace nada,sabe que debe hacer pero no sabe como hacerlo,digamos que es un tipo de asesor de clases,los métodos o procedimientos incluidos en las interfaces son abstractos,lo que quiere decir que no hacen nada hasta que se implementen en la clase que los use,para definiros hay que recordar que se escriben así:

abstract void hola(int parametro);

En void es el tipo de función o si es un procedimiento es void.

En hola es el nombre de la función o procedimiento.

en (int parámetro) van los parámetros o los dejamos vació si es que no lleva alguno.

No lleva llaves,ni siquiera vacías.

Bien,una interfaz va en su propio archivo y igual que las clases se llama igual que dicho archivo,es .java:


Vamos usar el ejemplo mas usado(que es el mejor):

Creamos una interfaz Poligono,el cual representa figuras geométricas,la clase tendrá las funciones para sacar la Area y el Perimetro de una figura:


1
2
3
4
5
6
package figuras;

public interface Poligono {
 public abstract void Area();
 public abstract void Perimetro();
}

Vamos a crear tres clases mas,la primera es el main,Figuras.java:


1
2
3
4
5
6
7
package figuras;

public class Figuras {
 public static void main(String args[]) {
  // Codigo
 }
}

La segunda va a ser una abstracción de un cuadrado que implemente la interfaz Polígono y defina las funciones de Área y Perímetro:

Para implementar una interfaz se usa la palabra implements seguida del nombre de la clase o de la clase que herede la clase,si se implementan varias interfaces se usan comas:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package figuras;

public class Cuadro implements Poligono{
 private int lado;
 Cuadro(int lado) {
  this.lado = lado;
 }
 
 public void Area() {
  int area = this.lado * this.lado;
  System.out.println("Area : "+area);
 }

 public void Perimetro() {
  int perimetro = this.lado+this.lado+this.lado+this.lado;
  System.out.println("Perimetro : "+perimetro);
 }

}

Bien como vemos los métodos abstractos ya los esta usando la clase Cuadro,algo muy importante es que los métodos se deben escribir si o si en la clase que los implemente o de lo contrario dará un error,si la clase no los usa pero si los define se puede usar esta sintaxis,por ejemplo :

public void Perimetro() { ; };
Aquí es donde comienza el upcasting,podemos definir un cuadro de la siguiente manera:

La manera normal seria:

Cuadro cuadro = new Cuadro(30);

Pero podemos hacerlo desde la clase heredada(que es una interfaz),subiendo un nivel en la cadena:

Poligono cuadro = new Cuadro(30);

Y no hay ningún problema.

El otro ejemplo que les mencionaba de el uso de interfaces como plantillas es que digamos que un programador encargado de pensar la idea de un programa crea una interfaz que tienen que definir los métodos otros programadores,pero  cada uno lo hará diferente,basado en la necesidad del objeto que debe crear,saben que deben hacer basados en la interfaz,pero les toca implementar el método.

A pequeña escala supongamos que el primer programador tenia que hacer un Cuadro,ya lo hizo y otro tiene que hacer un Rectangulo,lo cual se vería así:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package figuras;

public class Rectangulo implements Poligono {
 int base;
 int altura;
 Rectangulo(int base,int altura) {
  this.base = base;
  this.altura = altura;
 }
 
 public void Area() {
  int area = this.base * this.altura;
  System.out.println("Area : "+area);
 }

 public void Perimetro() {
  int perimetro = (this.base+this.base)+(this.altura+this.altura);
  System.out.println("Perimetro : "+perimetro);

 }

}


Ahora si en la clase principal podemos usarlos:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package figuras;

public class Figuras {
 public static void main(String args[]) {
  Poligono cuadro = new Cuadro(30);
  cuadro.Perimetro();
  cuadro.Area();
  Poligono rectangulo = new Rectangulo(20, 10);
  rectangulo.Area();
  rectangulo.Perimetro();
 }
}


Eso es todo :D.


Leer más...

viernes, 11 de abril de 2014

Tutorial Java en Linux Basico 8

Estructuras dinámicas

En esta ocasión vamos a ver como declarar estructuras dinámicas en java,las llamadas arrays.

En ocasiones anteriores hemos visto los arreglos de una dimensión llamados vectores y de dos llamados matrices,a diferencia de los arreglos comunes que acabo de mencionar los arrays deben o son dinámicos en tamaño no estáticos,por ejemplo al definir un vector de 10 elementos de tipo int tenemos que hacer esto:

Integer  elementos[] = new Integer[10];

Pero si quisiéramos o mejor dicho si no supiéramos cuantos elementos va a tener el arreglo como le haríamos?

Aquí es donde entra ArrayList lo que seria como una simple lista en lenguajes como python o ruby.

Listas

Para usar ArrayList tenemos que importarlo:

import java.util.ArrayList;

Su constructor es este:

ArrayList elementos = new ArrayList();

De esta manera seria idéntico a un lenguaje de alto nivel(fácil) crear una lista,a lo que me refiero es que podemos crear una lista de distintos tipos de datos,int,string,float,etc a diferencia de lo que seria un vector de un solo tipo de dato:


Para añadir un elemento usamos el método add pasándole como parámetro el dato a usar,por ejemplo:

elementos.add("Hola Mundo"); // String

elementos.add(10); // int

elementos.add('a'); // char

Bien,aun asi cuando los llamemos se convertiran a un tipo envuelto:

int a Interger

char a Character // etc


Aun así no es muy recomendable usar este tipo de listas(con datos de muchos tipos),lo recomendable es usar un dato de un solo tipo ya que incluso el compilador muestra un error.

Para definir el tipo de datos que vamos a usar lo añadimos al lado del constructor entre etiquetas:

ArrayList arreglo = new ArrayList();


En donde tipo usamos un tipo envuelto,por ejemplo:

ArrayList arreglo = new ArrayList();

Primero vamos a ver los métodos de agregar y de obtener:

arreglo.add(10);
arreglo.add(120);

Ya hemos comentado el método add,para obtener un elemento del arreglo usamos el método get y le pasamos como parámetro el índice(comienza a contar desde 0) del elemento:

arreglo.get(10);

Si queremos ver el tamaño de un arreglo usamos el método size que nos devuelve un int,por ejemplo para recorrer los elementos de un array:

for (int i = 0;i < arreglo.size();i++)
    System.out.println(arreglo.get(i));


Antes de ver las otras funciones podemos ver que añadir tiene otra función,la cual es diferente,mientras el add normal "apila" los datos uno sobre otro,este otro add puede añadir un dato en cierta posición:

arreglo.add(posición,elemento);

Eso seria como un remplazar.

Bien ahora vamos a ver las formas de iterar los elementos de un array,forma uno:

Esta ya la vimos:

for (int i = 0;i < arreglo.size();i++)
    System.out.println(arreglo.get(i));


Forma dos:

Con un bucle foreach,donde Integer es el tipo de Objeto.

for (Integer x: arreglo) {
    System.out.println(x);
}


Forma tres con un Iterator,donde Integer no es el tipo de objeto.

import java.util.Iterator;

Iterator i = arreglo.iterator();

while(i.hasNext()) {
    System.out.println(i.next());
}


Bien que mas podemos hacer?

Tenemos mas funciones:

arreglo.clear(); // Limpia el array(lo resetea)

arreglo.contains(elemento); // Devuelve true si existe el elemento en el array


arreglo.remove(indice); // elimina un elemento basado en el índice

arreglo.remove(elemento); // elimina un elemento basado en el elemento

arreglo.toArray(); // Devuelve un array (Object[])

arreglo.indexOf(elemento); // Devuelve el índice del elemento contando desde la izquierda

arreglo.lastIndexOf(elemento); // Devuelve el índice del elemento contando desde la derecha



Hashes

Ahora vamos a ver como usar los arreglos asociativos o has tables,los cuales se usan igual que las listas solo que se usan con clave valor en vez de índice valor:

Para definir un Hashtable,primero lo importamos:

import java.util.Hashtable;

Ahora usamos este constructor:

Hashtable hash;

Los dos objetos son los que usaremos para clave y valor,se recomienda usar String para clave,por ejemplo:

Hashtable hash = new Hashtable();

Ahora vamos a ver como añadir elementos:

Usamos:

hash.put(clave,valor);

Por ejemplo usando el hash de arriba:

hash.put("uno",1);
hash.put("diez",10);

Ahora tenemos dos elementos en el hash,como los recuperamos?

hash.get(clave);

Por ejemplo:

hash.get("uno"); // devuelve 1

Tenemos funciones similares al de ArrayList:

hash.clear(); // Resetea el hash

hash.containsKey(clave); // Devuelve true si contiene la clave

hash.containsValue(valor); // Devuelve true si contiene el valor

hash.isEmpty(); // Devuelve true si esta vacio

hash.remove(clave); // Quita el objeto basado en clave


Como iteramos?

Aquí es un poco mas complicado ya que no podemos usar índices,pero aun así tenemos algunas opciones:

La primera opciones es usando Collection ,primero importamos:

import java.util.Collection;

Ahora creamos un objeto Collection,esta nos devolverá los valores:

Collection  col = hash.values(); // En donde Integer es el tipo de objeto de los valores
Luego creamos un Iterator,como con ArrayList y iteramos:

Iterator i = col.iterator();
while(i.hasNext()) {
  System.out.println(i.next());
}


Forma 2:

Esta otra forma es mas sutil ya que podremos usar las llaves y los valores,es usando Enumeration:

import java.util.Enumeration;

Enumeration en = hash.keys(); // En donde String es el tipo de Objeto de las claves

Bien ahora solo iteramos:

while(en.hasMoreElements()) {
      String key = en.nextElement();
      System.out.printf("Clave : %s Valor : %s\n",key,hash.get(key));
}






Eso es todo :D

Leer más...

domingo, 19 de enero de 2014

Como usar SHA en Java (hash texto)

En esta ocasión vamos a aprender a crear un password usando el algoritmo de SHA(Secure Hash Algorithm) sea 1,256,512,etc.

Para hacerlo es muy sencillo ya que java tiene librerías preparadas para esto,lo único que tenemos que hacer unas cuantas acciones con bytes.

Lo primero que tenemos que hacer es crear una instancia de un proveedor de seguridad(el encargado de darnos los algoritmos):

Por ejemplo : SHA-1 o SHA-256

Debemos importar:

import java.security.MessageDigest; // Para crear el hash

import java.security.NoSuchAlgorithmException; // Para manejar error

Vamos a definir una String que sera el texto pasado a SHA :

String password = "Tiempo de Tux"; 

Tenemos que obtener los bytes del String para trabajarlos,creamos un array de bytes:

byte[] passB = password.getBytes(); 

Ahora tenemos que crear la instancia de SHA:

 MessageDigest messageD = MessageDigest.getInstance("SHA-1");

Le pasamos el array de bytes como un update ya que solo es una instancia de momento:

messageD.update(passB);

Creamos otro array de bytes pero esta vez sera el hash devuleto por la funcion digest de la instancia de SHA:

byte[] bytes = messageD.digest();

Por ultimo debemos convertir los bytes a base 16 o base 64,como hexadecimal es mas fácil al usar los mismos tipos de datos del lenguaje,asi que vamos a usar este:

1
2
3
4
5
6
7
8
9
StringBuilder passS = new StringBuilder(); // Para usar una String mutable

for (byte b : bytes) { // Convertimos a hex
   passS.append(String.format("%02x:", b));
}

String finalStringSha = passS.toString();

System.out.println(finalStringSha);


Eso es todo ya solo falta compilar y ejecutar.

Aquí un código completo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

class Ejemplo {
	public static void main(String[] args) throws NoSuchAlgorithmException {

		if (args.length == 0) {
			uso();System.exit(1);
		}
		String AGM,password;
		if (args[0].equals("-s256"))
			AGM = "SHA-256";
		else if (args[0].equals("-s512"))
			AGM = "SHA-512";
		else 
			AGM = "SHA-1";
		
		if (args.length == 1) {
			password = args[0];
		} else {
			password = args[1];
		}
		
		byte[] passB = password.getBytes();

		MessageDigest messageD = MessageDigest.getInstance(AGM);

		messageD.update(passB);

		byte[] bytes = messageD.digest();

		StringBuilder passS = new StringBuilder();

		for (byte b : bytes) {
			passS.append(String.format("%02x:", b));
		}

		String finalStringSha = passS.toString();

		System.out.println(finalStringSha);

	}
	
	private static void uso() {
		System.out.println("Uso:");
		System.out.println("Programa Algoritmo ");
		System.out.println("Algoritmos: ");
		System.out.println("-s1 SHA-1");
		System.out.println("-s256 SHA-256");
		System.out.println("-s512 SHA-512");
	}

}

Lo compilan y lo ejecutan así por ejemplo:

java Ejemplo -s256 Linux


Eso es todo.
Leer más...

miércoles, 15 de enero de 2014

Tutorial Java en Linux Basico 6

En este tutorial veremos Objetos.

Un Objeto es una instancia de una clase,un Objeto se puede tratar separado de los demás teniendo sus propios métodos y variables,para crear un método de una clase se usa la sintaxis:

Clase objeto = new Clase();

Lo que se pasa entre paréntesis es lo que recibe como argumentos el constructor.

Vayamos por partes:

La clase mas simple y que siempre se usa es donde esta el main,por ejemplo nuestro programa HolaMundo.java tiene esto adentro:


1
2
3
4
5
class HolaMundo {
    public static void main(String [] args) {
        System.out.println("Hola Mundo");
    }
}

Como ven pueden pensar que el main es el constructor,pero primero hay que saber que es un constructor,en mis palabras un constructor es:

Una función que se ejecuta antes que ninguna para inicializar o ejecutar acciones especificas.

En java todas las clases publicas deben tener el nombre del archivo que las contiene,en este caso HolaMundo,porque el archivo es HolaMundo.java.

Como crear un constructor?

El constructor es una función sin retorno y sin modificadores,esta debe tener el mismo nombre de la clase,vamos a crear un constructor para ese código:


1
2
3
HolaMundo(int x) {
    System.out.println("Hola se a creado el objeto numero "+x);
}


Este constructor lo único que hace es mostrar el numero de veces que se ha creado el archivo,basado en el paso por argumentos,veamos el código completo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class HolaMundo {
    HolaMundo(int x) { // Constructor
        System.out.println("Hola se a creado el objeto numero "+x);
    }
    public static void main(String [] args) {
        System.out.println("Hola Mundo");
        for (int i = 1;i < 11;i++) {
            HolaMundo objeto = new HolaMundo(i); // Creamos objetos basados en el bucle
        }
    }
}


Eso demuestra como se crean los constructores y como es que se ejecutan,no es el mejor ejemplo y de hecho veo mala practica al usar una variable renovada en cada iteracion del bucle,pero eso no es lo que importa,lo que importa es ver como se ejecuta lo que esta adentro del constructor.

Algunas cosas que debemos saber de un constructor es que:

1. Siempre hay un constructor aunque no creemos uno javac lo hace por nosotros.

2. Puede haber mas de un constructor (overloaded;lo veremos mas adelante).

3. Repito, un constructor no lleva ni modificador y modificador de acceso.

Ahora si podemos ver algo un poco mas bueno que la mala practica de arriba,por ejemplo si queremos ver cuantas veces se ha creado un objeto usamos una variable static,como dije en el primer tutorial una variable de modificador static solo se crea una vez,solo una vez.

Algunas cosas que hay que saber o recordar de static:

1. No se considera OOP.

2. Solo se crea una vez.

3. Solo se pueden usar metodos static en métodos del mismo tipo de modificador(static),pero no así a la inversa.

4. Los métodos static en una clase se consideran métodos de clase y no métodos de objeto.

Veamos un ejemplo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Ejemplo {
 private static int veces = 0;

 Ejemplo() {
  System.out.println("Hola se a creado el objeto numero " + veces);
  veces++;
 }

 public static void main(String[] args) {
  System.out.println("Hola Mundo");
  Ejemplo objeto = new Ejemplo();
  Ejemplo objeto1 = new Ejemplo();
  Ejemplo objeto2 = new Ejemplo();
 }
}


De ese modo podemos usar esa variable static para ver como cuantas veces se ejecuta,como dije los métodos static en una clase se llaman métodos de clase,para llamarlos no necesitamos crear un objeto,por ejemplo:


1
2
3
public static void getVeces() {
 System.out.println("Numero de objetos creados: "+veces);
}

Para usar este metodo no tenemos que instanciar un objeto y luego llamar el metodo:

Ejemplo objeto = new Ejemplo();

objeto.getVeces();

Aunque si funciona,lo que podemos hacer es:

Ejemplo.getVeces(); // Directamente

O mejor aun,las variables static se llaman variables de clase y podemos llamarlas asi:

Ejemplo.veces;

Código completo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Ejemplo {
 private static int veces = 0;

 Ejemplo() {
  System.out.println("Hola se a creado el objeto numero " + veces);
  veces++;
 }

 public static void main(String[] args) {
  System.out.println("Hola Mundo");
  Ejemplo objeto = new Ejemplo();
  Ejemplo objeto1 = new Ejemplo();
  Ejemplo objeto2 = new Ejemplo();
  Ejemplo.getVeces();
 }

 public static void getVeces() {
  System.out.println("Numero de objetos creados: "+veces);
 }
}


Como vemos estamos trabajando solo con la clase del main,pero como creamos nuevas,para crear otras clases podemos hacerlo de distintas maneras para distintas ocasiones,ya que podemos crear clases locales,anónimas,etc pero en este caso veremos clases normales,al gual que la que guarda el main.

Para crear una clase creamos un archivo en el mismo PATH(directorio) donde esta el main,en su momento también hablaremos de paquetes,pero de momento creen una clase,llamada Animales.java:

Esta clase va ademas de la que contiene el main que se llama Ejemplo.java:

vim Animales.java
La clase debe ser publica y el nombre debe ser el mismo del archivo:

public class Animales {

}

Vamos a crear unas funciones y variables para definir un animal,las cuales deben ser private:

Las variables private solo son visibles para la misma clase,objeto instanciado no lo podra llamar,lo cual hace que sean ocultadas para todo lo que no sea la misma clase,a esto se le conoce en el OOP como encapsulamiento.

Vamos a crear las variables:

private String especie;
private String sexo;
private boolean hambre = true;

Luego vamos a crear un constructor que reciba como parámetros las mismas variables,pero estas seran para definir las variables miembro(las de arriba):

Animales (String e,String s) {
       especie = e;
       sexo = s;
}

Ahora debemos crear una funcion que nos muestre el nombre,el sexo y si tiene hambre,ademas de una funcion para dar de comer:

Primero las funciones para ver el sexo y la especie,como son variables privadas no las podemos ver,asi que vamos a retornarlas como String,para ello tenemos que usar el token this,ya que this hace referencia a la variable del objeto actual,asi:

public String getEspecie() {
return this.especie;
}

Código completo:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Animales {
 private String especie;
 private String sexo;
 private boolean hambre = true;
 public Animales(String e,String s) {
  especie = e;
  sexo = s;
 }
 public String getSexo() {
  return this.sexo;
 }
 public String getEspecie() {
  return this.especie;
 }
 public void tienesHambre() {
  if (hambre)
   System.out.println("Tengo hambre :(");
  else 
   System.out.println("No tengo hambre :D");
 }
 public void darDeComer() {
  this.hambre = false;
 }
}

Como ven uso this para retornar,pero tambien se puede usar para definir,por ejemplo que los parámetros tuvieran el mismo nombre,usariamos this para hacer referencia a la variable miembro:


1
2
3
4
public Animales(String especie,String sexo) {
 this.especie = especie;
 this.sexo = sexo;
}

Ahora en la clase Ejemplo podemos crear un animal:


1
2
3
4
5
6
class Ejemplo {
 public static void main(String[] args) {
  Animales Mono = new Animales("Primate", "Macho");
  System.out.println(Mono.getEspecie());
 }
}

De esa manera hemos usado una clase mas ademas de la que contiene el main,podemos crear tantos animales como queramos y nuevos métodos,pero eso no es lo importante ahora ya que por ejemplo,en este ejemplo a la hora de comer se define en true,pero como vuelve a false(darle hambre de nuevo),pues esto lo veremos cuando veamos Threads,y como poder definir un animal mas especifico,esto lo veremos en herencia,pero de momento solo vimos como crear un objeto de una clase ajena al main.

Al ejecutar veremos esto:


Bien,algo que falta explicar en este tutorial basico de creación de objetos es la sobrecarga de métodos en la cual también veremos la sobrecarga de constructores:

En una clase puede haber distintos metodos con el mismo nombre,pero como se diferencian?

Con el simple hecho del paso por parametros:

Podemos tener estas dos funciones en la misma clase:


1
2
3
4
5
6
7
public void verNumero() {
 System.out.println(veces);
}
public void verNumero(String x) {
 System.out.println(x+veces);
 
}

Esto hará que podamos usar en el objeto:

Objeto.verNumero();

o

Objeto.verNumero("Veces creado : ");

Como dije lo único que lo distingue son los parametros,podriamos decir que lo distinguen los retornos,pero no,ya que el compilador no puede reconocer esto:


1
2
3
4
5
6
7
public void verNumero() {
 System.out.println(veces);
}
public int verNumero() {
 return veces;
 
}

Bien,de igual manera pasa con los constructores,podemos definir dos constructores para los Animales,supongamos esto,podemos darle de comer antes de crearlo,asi que así seria el constructor:


1
2
3
4
5
public Animales(String e,String s,boolean x) {
 especie = e;
 sexo = s;
 hambre = x;
}

Esto aun teniendo el constructor pasado, de esta manera podemos usar dos constructores:

new Animales("Primate", "Hembra");

o


new Animales("Primate", "Hembra",false);

Aunque no se obstruye uno con otro es recomendable iniciar todos los constructores,para ello usamos this,pero ahora con parámetros:

Por ejemplo llamamos:

Animales mono = new Animales("Primate", "Hembra");
En el constructor usamos this antes que nada:


1
2
3
4
5
public Animales(String e,String s) {
 this(e,s,false);
 especie = e;
 sexo = s;
}

El this inicia el otro constructor.

Como dije al principio podemos si no usamos constructores el compilador creara uno,si existen variables miembro sin iniciar,las cuales iniciaremos en un método,las variables se inician al valor por defecto:

Por ejemplo int 0,String u Objeto null,etc:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class Ejemplo2 {
 private int vint;
 private boolean vbool;
 private char vchar;
 private short vshort;
 private long vlong;
 private double vdouble;
 private String vString;
 
 public void ver() {
  System.out.println(vint);
  System.out.println(vbool);
  System.out.println(vchar);
  System.out.println(vshort);
  System.out.println(vlong);
  System.out.println(vdouble);
  System.out.println(vString);
 }
}

En el main:


1
2
3
4
5
6
7
class Ejemplo {
   public static void main(String[] args) {
   Ejemplo2 ejemplo = new Ejemplo2();
   ejemplo.ver();
   }

}

Aqui terminal la sexta parte de los tutoriales de Java.


Leer más...