java linux file-association jdk1.5

Forma multiplataforma para abrir un archivo usando Java 1.5



linux file-association (8)

Puede usar la forma predeterminada del sistema operativo para abrirlo por usted.

  • Windows: "cmd / c fileName
  • Linux w / gnome " nombre de archivo gnome-abierto"
  • Linux w / Kde?
  • OSx " nombre de archivo abierto"

Estoy usando Java 1.5 y me gustaría iniciar la aplicación asociada para abrir el archivo. Sé que Java 1.6 introdujo la API de escritorio , pero necesito una solución para Java 1.5 .

Hasta ahora encontré la manera de hacerlo en Windows:

Runtime.getRuntime().exec(new String[]{ "rundll32", "url.dll,FileProtocolHandler", fileName });

¿Hay una forma de plataforma cruzada para hacerlo? ¿O al menos una solución similar para Linux ?


Solo como una adición: en lugar de gnome-open , usa xdg-open . Es parte de XdgUtils , que a su vez son parte del paquete de soporte de LSB Desktop (comenzando con 3.2).

Puede (debería) seguir utilizando gnome-open como alternativa, pero xdg-open también funcionará en escritorios que no sean de GNOME.


JDIC es una biblioteca que proporciona funcionalidad similar a Desktop en Java 1.5.


SWT le brinda la posibilidad de solicitar que el programa estándar abra un archivo a través de:

final Program p = Program.findProgram(fileExtension); p.execute(file.getAbsolutePath());

Estrictamente, esto no es multiplataforma ya que SWT depende de la plataforma, pero para cada plataforma puede usar un jarrón SWT diferente.


public static boolean isWindows() { String os = System.getProperty("os.name").toLowerCase(); return os.indexOf("windows") != -1 || os.indexOf("nt") != -1; } public static boolean isMac() { String os = System.getProperty("os.name").toLowerCase(); return os.indexOf("mac") != -1; } public static boolean isLinux() { String os = System.getProperty("os.name").toLowerCase(); return os.indexOf("linux") != -1; } public static boolean isWindows9X() { String os = System.getProperty("os.name").toLowerCase(); return os.equals("windows 95") || os.equals("windows 98"); }

y

if (isLinux()) { cmds.add(String.format("gnome-open %s", fileName)); String subCmd = (exec) ? "exec" : "openURL"; cmds.add(String.format("kfmclient "+subCmd+" %s", fileName)); } else if (isMac()) { cmds.add(String.format("open %s", fileName)); } else if (isWindows() && isWindows9X()) { cmds.add(String.format("command.com /C start %s", fileName)); } else if (isWindows()) { cmds.add(String.format("cmd /c start %s", fileName)); }


Otra respuesta (por boutta) sugiere usar SWT. No recomendaría hacer referencia a la biblioteca solo para este propósito, pero si ya la está utilizando, simplemente ejecute:

Program.launch("http://google.com/");

Tenga en cuenta que este método solo funcionará (y devolverá true ) si un objeto Display ya se ha creado (por ejemplo, al crear un Shell ). También tenga en cuenta que debe ejecutarse en el hilo principal; p.ej:

Display.syncExec(new Runnable() { public void run() { Program.launch("http://google.com/"); } });

En el ejemplo anterior, he lanzado una URL, pero el inicio de archivos funciona de la misma manera.


+1 por esta respuesta

Además sugeriría la siguiente implementación usando polimorfismo:

De esta manera, puede agregar una nueva plataforma más fácilmente al reducir el acoplamiento entre las clases.

El código del cliente:

Desktop desktop = Desktop.getDesktop(); desktop.open( aFile ); desktop.imaginaryAction( aFile );

La impl de escritorio:

package your.pack.name; import java.io.File; public class Desktop{ // hide the constructor. Desktop(){} // Created the appropriate instance public static Desktop getDesktop(){ String os = System.getProperty("os.name").toLowerCase(); Desktop desktop = new Desktop(); // This uf/elseif/else code is used only once: here if ( os.indexOf("windows") != -1 || os.indexOf("nt") != -1){ desktop = new WindowsDesktop(); } else if ( os.equals("windows 95") || os.equals("windows 98") ){ desktop = new Windows9xDesktop(); } else if ( os.indexOf("mac") != -1 ) { desktop = new OSXDesktop(); } else if ( os.indexOf("linux") != -1 && isGnome() ) { desktop = new GnomeDesktop(); } else if ( os.indexOf("linux") != -1 && isKde() ) { desktop = new KdeDesktop(); } else { throw new UnsupportedOperationException(String.format("The platform %s is not supported ",os) ); } return desktop; } // default implementation :( public void open( File file ){ throw new UnsupportedOperationException(); } // default implementation :( public void imaginaryAction( File file ){ throw new UnsupportedOperationException(); } } // One subclass per platform below: // Each one knows how to handle its own platform class GnomeDesktop extends Desktop{ public void open( File file ){ // Runtime.getRuntime().exec: execute gnome-open <file> } public void imaginaryAction( File file ){ // Runtime.getRuntime().exec:gnome-something-else <file> } } class KdeDesktop extends Desktop{ public void open( File file ){ // Runtime.getRuntime().exec: kfmclient exec <file> } public void imaginaryAction( File file ){ // Runtime.getRuntime().exec: kfm-imaginary.sh <file> } } class OSXDesktop extends Desktop{ public void open( File file ){ // Runtime.getRuntime().exec: open <file> } public void imaginaryAction( File file ){ // Runtime.getRuntime().exec: wow!! <file> } } class WindowsDesktop extends Desktop{ public void open( File file ){ // Runtime.getRuntime().exec: cmd /c start <file> } public void imaginaryAction( File file ){ // Runtime.getRuntime().exec: ipconfig /relese /c/d/e } } class Windows9xDesktop extends Desktop{ public void open( File file ){ //Runtime.getRuntime().exec: command.com /C start <file> } public void imaginaryAction( File file){ //Runtime.getRuntime().exec: command.com /C otherCommandHere <file> } }

Esto es solo un ejemplo, en la vida real no vale la pena crear una nueva clase solo para parametrizar un valor (la cadena de comandos% s). Pero imaginemos que cada método realiza otros pasos de una manera específica para la plataforma.

Al hacer este tipo de acercamiento, se pueden eliminar los constructos innecesarios if / elseif / else que con el tiempo pueden introducir errores (si hay 6 de ellos en el código y se necesita un cambio, puede olvidarse de actualizar uno de ellos, o mediante copia / pegando puede olvidarse de cambiar el comando para ejecutar)


Nosotros ponemos el comando afuera en alguna parte en el archivo de configuración.

Su "JAR y código fuente" será "multiplataforma", pero su implementación no.

También puedes hacer algo como esta respuesta . Puede poner el nombre de clase de la clase de fábrica de la implementación "Deskop" en el archivo de instalación. (puede ser guía o primavera, si lo desea)