Foro de elhacker.net

Programación => Java => Mensaje iniciado por: VicInFlames en 2 Marzo 2015, 11:29 am



Título: Guardar valor de variables de .java en save.xml
Publicado por: VicInFlames en 2 Marzo 2015, 11:29 am
Muy buenas a todos,
tengo serias dudas con un proyecto en java que no acabo de comprender.

He programado un juego sobre las "Torres de Hanoi",con las clases :
-Tablero
-Disco
-Torre
-JugarTorres
aunque estas con lo de menos..

En el juego,debes especificar los movimientos que quieres hacer con los discos,de que posición a qué posición,guardando estas..
en ese caso,quiero guardar estas variables en un save.xml mediante las clases StaXParser.java,Item.java,y StaxWriter.java.. como he podido consultar en otras webs es la manera más sencilla..

He seguido los pasos necesarios,pero no consigo entender cómo adaptar el código al mío..añadir los eventos,los cambios de valores..
me es complicado ya que empecé recientemente con el mundo de Java..

necesito una extensa explicación de cómo podría solucionar mi problema,si es necesario paso mi código para facilitarlo.
A ser posible responder lo antes posible.

Agradecimientos adelantados


Título: Re: Guardar valor de variables de .java en save.xml
Publicado por: Usuario Invitado en 2 Marzo 2015, 13:16 pm
Usa el API de Java para manejo de XML, JAXB. Con JAXB puedes transformar un objeto a XML y viceversa. Te dejo un ejemplo aplicado a tu caso:


ENTIDADES


Board:

Código
  1. /**
  2.  *
  3.  * @author Gus
  4.  */
  5. public class Board {
  6.    private String name;
  7.    private int towersNumber;
  8.  
  9.    public Board() {}
  10.  
  11.    public Board(String name, int towersNumber) {
  12.        this.name = name;
  13.        this.towersNumber = towersNumber;
  14.    }
  15.  
  16.    public String getName() {
  17.        return name;
  18.    }
  19.  
  20.    public void setName(String name) {
  21.        this.name = name;
  22.    }
  23.  
  24.    public int getTowersNumber() {
  25.        return towersNumber;
  26.    }
  27.  
  28.    public void setTowersNumber(int towersNumber) {
  29.        this.towersNumber = towersNumber;
  30.    }
  31.  
  32.  
  33.  
  34. }
  35.  

Tower:

Código
  1. package net.elhacker.jaxbexample.model.entities;
  2.  
  3. /**
  4.  *
  5.  * @author Gus
  6.  */
  7. public class Tower {
  8.    private String name;
  9.    private int xAxis;
  10.    private int yAxis;
  11.  
  12.    public Tower() {}
  13.  
  14.    public Tower(String name, int xAxis, int yAxis) {
  15.        this.name = name;
  16.        this.xAxis = xAxis;
  17.        this.yAxis = yAxis;
  18.    }
  19.  
  20.    public String getName() {
  21.        return name;
  22.    }
  23.  
  24.    public void setName(String name) {
  25.        this.name = name;
  26.    }
  27.  
  28.    public int getxAxis() {
  29.        return xAxis;
  30.    }
  31.  
  32.    public void setxAxis(int xAxis) {
  33.        this.xAxis = xAxis;
  34.    }
  35.  
  36.    public int getyAxis() {
  37.        return yAxis;
  38.    }
  39.  
  40.    public void setyAxis(int yAxis) {
  41.        this.yAxis = yAxis;
  42.    }
  43.  
  44.  
  45. }

Disc:

Código
  1. package net.elhacker.jaxbexample.model.entities;
  2.  
  3. /**
  4.  *
  5.  * @author Gus
  6.  */
  7. public class Disc {
  8.    private int xAxis;
  9.    private int yAxis;
  10.  
  11.    public Disc() {}
  12.  
  13.    public Disc(int xAxis, int yAxis) {
  14.        this.xAxis = xAxis;
  15.        this.yAxis = yAxis;
  16.    }
  17.  
  18.    public int getxAxis() {
  19.        return xAxis;
  20.    }
  21.  
  22.    public void setxAxis(int xAxis) {
  23.        this.xAxis = xAxis;
  24.    }
  25.  
  26.    public int getyAxis() {
  27.        return yAxis;
  28.    }
  29.  
  30.    public void setyAxis(int yAxis) {
  31.        this.yAxis = yAxis;
  32.    }
  33.  
  34.  
  35. }

Ahora veamos a nuestra clase que se transformará en un archivo XML:

Código
  1. import javax.xml.bind.annotation.XmlAccessType;
  2. import javax.xml.bind.annotation.XmlAccessorType;
  3. import javax.xml.bind.annotation.XmlElement;
  4. import javax.xml.bind.annotation.XmlRootElement;
  5. import net.elhacker.jaxbexample.model.entities.Board;
  6. import net.elhacker.jaxbexample.model.entities.Disc;
  7. import net.elhacker.jaxbexample.model.entities.Tower;
  8.  
  9. /**
  10.  *
  11.  * @author Gus
  12.  */
  13. @XmlRootElement(name="HanoiTower")
  14. @XmlAccessorType(XmlAccessType.FIELD)
  15. public class HanoiTower {
  16.  
  17.    @XmlElement
  18.    public Tower tower;
  19.    @XmlElement
  20.    public Board board;
  21.    @XmlElement
  22.    public int playingTowers;
  23.    @XmlElement
  24.    public Disc disc;
  25.  
  26.    public HanoiTower() {
  27.    }
  28.  
  29.    public Tower getTower() {
  30.        return tower;
  31.    }
  32.  
  33.    public void setTower(Tower tower) {
  34.        this.tower = tower;
  35.    }
  36.  
  37.    public Board getBoard() {
  38.        return board;
  39.    }
  40.  
  41.    public void setBoard(Board board) {
  42.        this.board = board;
  43.    }
  44.  
  45.    public Disc getDisc() {
  46.        return disc;
  47.    }
  48.  
  49.    public void setDisc(Disc disc) {
  50.        this.disc = disc;
  51.    }
  52.  
  53.    public int getPlayingTowers() {
  54.        return playingTowers;
  55.    }
  56.  
  57.    public void setPlayingTowers(int playingTowers) {
  58.        this.playingTowers = playingTowers;
  59.    }
  60.  
  61. }
  62.  


Como puedes observar, hemos anotado la clase con @XmlRootElement. Esto indica que dicha clase será la raíz de una estructura XML. Ojo, esto no quiere decir que no puedas guardar un objeto anotado así en otro. Su atributo name es para asignarle un nombre a la raíz del XML.

@XmlAccessorType, especifica que tipo de acceso se tendrá la clase, si es por propiedades (campos) o métodos. En nuestro caso, hemos optado por que el acceso sea por medio de las propiedades: XmlAccessType.FIELD.

Las propiedades las hemos anotado con @XmlElement, esto indica que dicha propiedad será una etiqueta, y su valor se desplegará entre dicha etiqueta de apertura y la de su cierre.

Si te das cuenta aunque los objetos Board, Tower y Disc no hayan sido declarados con @XMLElement, JAXB lo hace por nosotros. Observa al final, la salida que genera JAXB.

Ahora veamos quién hace la "magia". En éste caso he creado una clase que actúe de manager para convertir de Objeto a XML y viceversa.

HanoiTowerMarshaller:

Código
  1. import java.io.File;
  2. import java.util.logging.Logger;
  3. import javax.xml.bind.JAXBContext;
  4. import javax.xml.bind.JAXBException;
  5. import javax.xml.bind.Marshaller;
  6. import javax.xml.bind.Unmarshaller;
  7.  
  8. /**
  9.  *
  10.  * @author Gus
  11.  */
  12. public class HanoiTowerMarshaller {
  13.    private static JAXBContext jaxbContext;
  14.    private static Logger logger;
  15.  
  16.    public HanoiTowerMarshaller() {
  17.        try {
  18.            jaxbContext  = JAXBContext.newInstance(HanoiTower.class);
  19.            logger = Logger.getLogger(HanoiTowerMarshaller.class.getName());
  20.        } catch(JAXBException ex) {
  21.            logger.warning(ex.getMessage());
  22.        }
  23.    }
  24.  
  25.    public void marshal(HanoiTower hanoiTower) {
  26.        try {
  27.            File file = new File("D:\\hanoi-tower.xml");
  28.            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
  29.  
  30.            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  31.  
  32.            jaxbMarshaller.marshal(hanoiTower, file);
  33.            jaxbMarshaller.marshal(hanoiTower, System.out);
  34.  
  35.        } catch(JAXBException ex) {
  36.            logger.warning(ex.getMessage());
  37.        }
  38.    }
  39.  
  40.    public HanoiTower unmarshall(String filePath) {
  41.        HanoiTower hanoiTower = null;
  42.        try {
  43.            File xml = new File(filePath);
  44.            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
  45.            hanoiTower = (HanoiTower) jaxbUnmarshaller.unmarshal(xml);
  46.        } catch (JAXBException ex) {
  47.            logger.warning(ex.getMessage());
  48.        }
  49.        return hanoiTower;
  50.    }
  51. }

Primero declaramos jaxbContext y logger como propiedades porque las utilizaremos en ambos métodos de la clase.

En el constructor inicializamos jaxbContext con el método newInstance() de JAXBContext al que debemos pasarle por parámetro la clase con la que se trabajará. Como siempre vamos a a trabajar con HanoiTower, se lo indico aquí. Si vamos a trabajar con muchas clases y XML, esto debe ir en el método marshal y unmarshal ya que las clases con las que se va a trabajar son varias.

También inicializamos logger. Logger lo único que hace es crear logs para que los puedas revisar luego en caso de error o algo importante.

En el método marshall, lo primero que hacemos es crear un objeto File con la ruta recibida, esto para saber dónde guardar el XML.

Luego simplemente crea un objeto Marshaller para poder llevar a cabo la conversión. Posteriormente le asignamos una propiedad para que el código esté formateado, esto por cuestiones de legibilidad ;) ).

Por último, utilizamos el método marshal para convertir el objeto a XML y guardarlo en la ruta a la que apunta el objeto File. También lo hacemos con System.out porque quiero ver la salida en la consola también.

El método unmarshall hace lo mismo, la diferencia es que crea un objeto Unmarshaller y utiliza el método unmarshal pasándole el objeto File que apunta a la ruta del XML a leer. Nota el cast, es necesario usarlo.

Ahora, una pequeña prueba:

JAXBExample:

Código
  1. package jaxbexample;
  2.  
  3. import net.elhacker.jaxbexample.model.entities.Board;
  4. import net.elhacker.jaxbexample.model.entities.Disc;
  5. import net.elhacker.jaxbexample.model.entities.Tower;
  6. import net.elhacker.jaxbexample.model.xml.HanoiTower;
  7. import net.elhacker.jaxbexample.model.xml.HanoiTowerMarshaller;
  8.  
  9. /**
  10.  *
  11.  * @author Gus
  12.  */
  13. public class JAXBExample {
  14.  
  15.    public static void main(String[] args) {
  16.        HanoiTowerMarshaller marshaller = new HanoiTowerMarshaller();
  17.        Board board = new Board();
  18. Tower tower = new Tower();
  19. Disc disc = new Disc();
  20.  
  21. board.setName("Juego 1");
  22. board.setTowersNumber(5);
  23. tower.setName("Torre 1");
  24. tower.setxAxis(25);
  25. tower.setyAxis(34);
  26. disc.setxAxis(19);
  27. disc.setyAxis(23);
  28. HanoiTower hanoiTower = new HanoiTower();
  29. hanoiTower.setBoard(board);
  30. hanoiTower.setTower(tower);
  31. hanoiTower.setDisc(disc);
  32. hanoiTower.setPlayingTowers(7);
  33.  
  34.        marshaller.marshal(hanoiTower, "D:\\hanoi-tower.xml");
  35.  
  36.        HanoiTower xmlToHanoiTower = marshaller.unmarshall("D:\\hanoi-tower.xml");
  37.        System.out.println("Datos del juego cargado:\n");
  38.        System.out.println("Nombre del juego:");
  39.        System.out.println(xmlToHanoiTower.getBoard().getName());
  40.        System.out.println("Número de torres en el juego:");
  41.        System.out.println(xmlToHanoiTower.getBoard().getTowersNumber());
  42.        System.out.println("Nombre de la torre del jugador:");
  43.        System.out.println(xmlToHanoiTower.getTower().getName());
  44.        System.out.println("Coordenada X de la torre:");
  45.        System.out.println(xmlToHanoiTower.getTower().getxAxis());
  46.        System.out.println("Coordenada Y de la torre:");
  47.        System.out.println(xmlToHanoiTower.getTower().getyAxis());
  48.        System.out.println("Número de torres jugando:");
  49.        System.out.println(xmlToHanoiTower.getPlayingTowers());
  50.        System.out.println("Coordenada X del disco:");
  51.        System.out.println(xmlToHanoiTower.getDisc().getxAxis());
  52.        System.out.println("Coordenada Y del disco:");
  53.        System.out.println(xmlToHanoiTower.getDisc().getyAxis());
  54.    }
  55.  
  56. }


Salida:

Código:
<HanoiTower>
    <tower>
        <name>Torre 1</name>
        <xAxis>25</xAxis>
        <yAxis>34</yAxis>
    </tower>
    <board>
        <name>Juego 1</name>
        <towersNumber>5</towersNumber>
    </board>
    <playingTowers>7</playingTowers>
    <disc>
        <xAxis>19</xAxis>
        <yAxis>23</yAxis>
    </disc>
</HanoiTower>
Datos del juego cargado:

Nombre del juego:
Juego 1
Número de torres en el juego:
5
Nombre de la torre del jugador:
Torre 1
Coordenada X de la torre:
25
Coordenada Y de la torre:
34
Número de torres jugando:
7
Coordenada X del disco:
19
Coordenada Y del disco:
23

Enjoy!


Título: Re: Guardar valor de variables de .java en save.xml
Publicado por: VicInFlames en 15 Noviembre 2015, 18:57 pm
Wooooow! xD Muchisimas gracias por la ayuda.
Quizás algo tarde..~ pero muy muy valiosa información.
Tendré que repasar algo de xml..