Кроссплатформенный способ открыть файл с помощью Java 1.5 - PullRequest
11 голосов
/ 28 ноября 2008

Я использую Java 1.5, и я хотел бы запустить соответствующее приложение, чтобы открыть файл. Я знаю, что Java 1.6 представила Desktop API , но мне нужно решение для Java 1.5 .

Пока я нашел способ сделать это в Windows:

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

Есть ли кросс-платформенный способ сделать это? Или хотя бы аналогичное решение для Linux ?

Ответы [ 8 ]

12 голосов
/ 28 ноября 2008

JDIC - это библиотека, которая обеспечивает функциональность, аналогичную Desktop в Java 1.5.

12 голосов
/ 28 ноября 2008
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");
}

и

 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));
  }
11 голосов
/ 28 ноября 2008

+ 1 для этот ответ

Кроме того, я бы предложил следующую реализацию с использованием полиморфизма:

Таким образом, вы можете упростить добавление новой платформы, уменьшив связь между классами.

Код клиента:

 Desktop desktop = Desktop.getDesktop();

 desktop.open( aFile );
 desktop.imaginaryAction( aFile );

Рабочий стол impl:

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>
    }
}

Это только пример, в реальной жизни не стоит создавать новый класс только для параметризации значения (командная строка% s). Но давайте представим, что каждый метод выполняет другие шаги в зависимости от платформы.

При таком подходе можно удалить ненужные, если / elseif / else создает, что со временем может привести к ошибкам (если в коде их 6, а изменение необходимо, вы можете забыть обновить один из них, или скопировав / вставив, вы можете забыть изменить команду для выполнения)

5 голосов
/ 29 ноября 2008

Как дополнение: вместо gnome-open используйте xdg-open. Это часть XdgUtils , которые, в свою очередь, являются частью пакета поддержки LSB Desktop (начиная с 3.2).

Вы можете (должны) по-прежнему использовать gnome-open в качестве запасного варианта, но xdg-open также будет работать на десктопах без GNOME.

4 голосов
/ 28 ноября 2008

SWT дает возможность lokk для стандартной программы открыть файл через:

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

Строго говоря, это не кроссплатформенность, поскольку SWT зависит от платформы, но для каждой платформы вы можете использовать разные SWT-банки.

0 голосов
/ 17 ноября 2010

В другом ответе (от boutta) предлагается использовать SWT. Я бы не рекомендовал ссылаться на библиотеку только для этой цели, но если вы уже используете ее, просто выполните:

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

Обратите внимание, что этот метод будет работать (и вернет true), только если объект Display уже создан (например, путем создания Shell). Также обратите внимание, что он должен работать в основном потоке; e.g.:

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

В приведенном выше примере я запустил URL, но запуск файлов работает аналогично.

0 голосов
/ 28 ноября 2008

Мы помещаем команду снаружи где-то в файле конфигурации.

Ваш «JAR и исходный код» будет «кроссплатформенным», но ваше развертывание - нет.

Вы также можете сделать что-то вроде этого ответа . Вы можете поместить имя класса фабричного класса реализации Deskop в установочный файл. (может быть гидом или весной, если хотите)

0 голосов
/ 28 ноября 2008

Вы можете использовать способ ОС по умолчанию, чтобы открыть его для вас.

  • Windows: "cmd / c fileName
  • Linux w / gnome "gnome-open filename "
  • Linux с Kde ??
  • OSx "открыть имя файла "
...