Foro sobre Java SE > Ejecutar JAR
El anterior es la linea 45, aqui esta el bloque.
public aho() {
initComponents();
this.setLocationRelativeTo(null);
arch = new File("src\\fichero.xml");
SAXBuilder constructorSAX = new SAXBuilder();
try {
doc = (Document)constructorSAX.build(arch);
} catch (JDOMException e) {
System.out.println("Fichero XML no valido");
e.printStackTrace();
} catch (IOException e) {
System.out.println("Fichero no valido");
e.printStackTrace();
}
nodoRaiz = doc.getRootElement();
List listaAplicaciones = nodoRaiz.getChildren("palabra");
for (int i=0; i<listaAplicaciones.size(); i++) {
Element nodo = (Element)listaAplicaciones.get(i);
items[i] = nodo.getAttribute("id").getValue();
}
Creo que el problema está aquí:
arch = new File("src\\fichero.xml");
porque estás usando una ruta relativa... a ningún sitio. Ni el Sistema Operativo ni Java pueden localizar un archivo externo, con esa dirección.
No sé si ese archivo tiene que estar forzosamente en el sistema de archivos del Sistema Operativo, o puede estar localizable dentro del jar de la aplicación, si es que no se va a modificar.
Para cada caso hay una solución diferente. Tu dirás.
Pues en principio seria modificable, pero la intención es que acompañara a la aplicación, por eso lo puse en la carpeta src del proyecto, si no es mucha molestia y me puedes comentar como hacerlo... Si no hay una solución lo haré que no se pueda modificar, pero entonces la ruta seria correcta no?
El error es sin duda la ruta al fichero que estas poniendo.
Vamos por partes, por un lado está la ruta de los fuentes y por otro la de los ejecutables.
Cuando tu compilas los fuentes que están bajo la carpeta "src" son movidos a la carpeta donde estén, siendo "bin" o "classes" las mas comunes.
Por ejemplo: si tu sienes una ruta tal que "proyecto/src/carpeta1/carpeta2/nomFichero.java" cuando compilas se crea la ruta o estructura de dicheros: "proyecto/classes/carpeta1/carpeta2/nomFichero.class"
Como ves tu fichero XML lo se encuentra porque tu aplicación lo busca en la ruta de salida que no existe.
Eso por un lado. Por otro tenemos que has creado un jar. Tienes que buscar el fichero dentro del jar y con la ruta de dentro del jar. Me explico, cuando tu creas un jar los ficheros que se guardan en el son los ejecutables solo, es decir, los ficheros que hay por debajo de "bin" o "classes" segun hayas establecido, y la ruta debe ser completa desde aqui y con un separador de paquetes "." y no "/".
Tampoco vale poner la ruta y mas, tienes que decirle a tu aplicación donde está y que lo extraiga para poder leerlo. Googlea un poco y veras como se hace.
Una pista, busca por esto "getResourceAsStream"
Si el xml lo tienes fuera del jar no hay problema, pon la ruta completa al fichero tal y como lo hacías y ya.
Un saludo.
Puedes incluir ese archivo como un recurso más, con lo que estará incluido dentro del jar de la aplicación. En este caso, se comporta como un archivo de solo lectura, puesto que no se podrá modificar por la aplicación.
Puedes añadirlo a un package cualquiera, y en tu caso acceder a el así:
InputStream archivoXML = getClass().getResourceAsStream("/package1/package12/../fichero.xml");
donde esos package son la ruta absoluta del fichero.xml hasta el raíz de tu proyecto.
Ese archivoXML ya puedes pasarlo directamente al build de SAXBuilder, puesto que admite parámetros del tipo InputStream.
Si lo que deseas es incluirlo en la distribución como un archivo externo al jar, lo más recomendable es que lo añadas a una ruta relativa a la carpeta del Sistema Operativo, desde donde sabes que se ejecuta el jar.
En tu caso, puedes añadirlo a la carpeta dist, o a cualquier subcarpeta que debes crear dentro de dist.
Para acceder a el puedes usar esta propiedad de Java
String dir= System.getProperty("user.dir");
que devuelve un String con la ruta absoluta de la carpeta dist. Si incluyes el archivo, digamos en una subcarpeta archivos dentro de dist:
arch = new File(dir.concat("/archivos/fichero.xml"));
Guenas.
Yo lo que te aconsejo es que utilices el path donde esta el jar para usar un directorio relativo al mismo. Hazte una rutina para averiguar donde esta el jar que se esta ejecutando.
Presumir que el jar esta en X es absurdo. Yo mismo nunca pongo la aplicación donde se ofrece sino donde me sale de los mismísimos.
Nunca, nunca , jamas, bajo ningún concepto se debe usar un path fijo. Siempre relativo a la aplicación o a algo concreto definido con absoluta certeza. A malas usa el acceso al registro para guardar/leer donde se encuentra todo.
El metodo del classloader es el adecuado si no tienes que modificarlo y en segun que condiciones puedes usarlo para leer el "default" y escribir en una localización definida una copia que si sea modificable y perfectamente controlada por tu aplicacion.
Un saludo
Guenas.
Por si no sabes como localizar donde esta el jar usa:
ClasePrincipal.class.getProtectionDomain().getCodeSource().getLocation();
siendo ClasePrincipal la que contiene tu main()
Te devolvera la URL de tu jar y ese es el path absoluto al que referir tu path relativo.
Todo lo demas de usar paths fijos o presupuestos como java.user.path no es en absoluto seguro. Jamas lo hagas.
Un saludo
@Paposo
Me gustaría saber dos cosas:
1.- Si lo que se necesita, para una aplicación de escritorio, es una ruta a la carpeta de inicio de la aplicación, ¿A qué viene buscar un URL, cuando se puede obtener la ruta directamente, y en el formato específico del Sistema Operativo?.
2.- ¿Qué tiene de "inseguro" el método System.getProperty("user.dir");
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#getProperties()
No es una aplicación que se ejecute mediante el plugin de un navegador.
" Access to system properties can be restricted by the Security Manager. This is most often an issue in applets, which are prevented from reading some system properties"
http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
"Typically, a web applet runs with a security manager provided by the browser or Java Web Start plugin. Other kinds of applications normally run without a security manager, unless the application itself defines one. If no security manager is present, the application has no security policy and acts without restrictions."
http://docs.oracle.com/javase/tutorial/essential/environment/security.html
"This topic lists system properties that can be accessed by rich Internet applications (RIAs) that are restricted to the security sandbox and are launched with or without the Java Network Launch Protocol (JNLP). Some system properties cannot be accessed by sandbox RIAs.
Forbidden System Properties
Sandbox RIAs cannot access the following system properties:
java.class.path
java.home
user.dir
user.home
user.name"
http://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/properties.html
Lo que no es el caso presente, puesto que se trata de una aplicación de escritorio, no un RIA. En el caso de que fuese un RIA, no se trataría de que el acceso al user.dir fuera inseguro, sino que el sandbox no lo permitiría
Guenas.
Amigo Choces.
Lo inseguro es que el jar no tiene porque estar en user.dir.
Simplemente eso.
Lo que le he propuesto funciona absolutamente siempre, este donde este.
Un saludo
@Paposo
La propiedad user.dir la establece la VM en el momento en que se inicia la aplicación, y contiene la ruta, en términos del Sistema Operativo, de la carpeta desde donde se lanza la aplicación.
[EDIT] anteriormente decía, erróneamente, que apuntaba a la ubicación donde estaba el main,
en vez de lo correcto, que es lo que se ha corregido en el párrafo anterior, y lo que he comentado en varios otros mensajes, incluido éste mismo. Un lapsus.
Al contrario de lo que muchas veces se cree, user.dir no es una propiedad estática, con un valor predefinido, al margen del instante de la ejecución de la aplicación.
"The System class maintains a Properties object that describes the configuration of the current working environment."
http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
Por lo tanto, da igual dónde se instale, se copie, o se ejecute el jar de la aplicación: esa propiedad siempre apunta a la ruta actual de ejecución: es el llamado "current working dir" en los Javadocs.
Y lo que yo he propuesto, también funciona siempre, no es en absoluto inseguro desde ningún punto de vista, para una aplicación de escritorio, y el código es más sencillo y más claro.
@choces
Temo que no.
user.dir apunta al directorio desde el que se ejecuta algo. No al directorio donde se encuentra el jar.
Por ejemplo si ejecutas desde el directorio DIRPADRE la sentencia:
java -jar DIRHIJO/MiApp.jar
la propiedad user.dir apunta a DIRPADRE en lugar de a DIRHIJO
No siempre las aplicaciones se ejecutan desde el mismo directorio en el que están instaladas
Un saludo
@Paposo
[EDIT] Después de hacer la corrección en el mensaje anterior, simplemente se me olvidó hacer una referencia en este mismo mensaje, como era debido. Por eso, ahora edito ambos mensajes.
El objeto del user.dir es conocer la carpeta desde donde se lanza la aplicación, para proporcionar al programador una referencia relativa al sistema de archivos, que no tiene por qué conocer durante el desarrollo, puesto que Java se puede ejecutar en diversas plataformas, y la aplicación se puede instalar en cualquier sitio.
Esa referencia le permite, como en el caso de este hilo, poder crear nuevas carpetas, acceder a archivos externos a la aplicación, bases de datos, y lo que necesite del sistema de archivos, conociendo la ruta de trabajo.
No importa en absoluto dónde esté el jar de la aplicación, sino saber dónde están las carpetas y los archivos de trabajo de la aplicación.
La persona que inició este hilo, declaró que era novato en Java, y creo que le hacemos un mal favor con este tipo de disquisiciones, cuando lo que necesitaba, desde un principio, era una manera sencilla de entender y resolver el problema que tenía, para acceder a un archivo de su aplicación.
@choces
¡Impresionante!
Tienes un par de huevos. El post que escribiste no ponía lo que pone ahora. Lo has modificado para quedar bien, con un morro que te cagas.
Aunque siempre había considerado que sabias mucho y yo mismo he aprendido de lo que decías, ahora lo que considero es que te burlas de todos para satisfacer tu ego.
La gente con mente o con memoria seguro que te ha calado, Mourinho,
La gente honesta reconoce, como yo he hecho varias veces, que el que tiene boca se equivoca. Tu no.
Vale. Master del universo. Eres un genio incontestable que jamas se equivoca. Lamento haber dicho algo que pueda poner en duda tu extrema sapienza.
Sabes, pero eres patético y peligroso, porque jamas admites o admitirás tus errores,
Bueno, compañeros, a partir de ahora reconozco que solo vale lo que dice el amigo choces, sobrado, creido, que no tiene ningún problema en falsear datos para quedar bien. Y aun así no lo logra.
Hasta luego, patético. Jamas te llevare la contraria porque gente así es capaz de cualquier cosa y me da miedo.
Estoy convencido de que el administrador de la web es capaz de confirmar que el post del amigo choces ha sido modificado bastante después de haber leido mi respuesta.
Yo lo se y choces tambien. Probablemente muchos mas a los que choces trata de gilipollas.
De verdad que estas enfermo y necesitas ayuda médica.
Un saludo a todos y mis mas sinceras condolencias a quien conviva con alguien que siendo muy bueno en lo suyo llega a estos extremos para no aceptar que es humano y que sin duda alcanza la categoria de dios.
doc = (Document)constructorSAX.build(arch);