2008-11-28 2 views
11

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

До сих пор я нашел способ сделать это в Windows:

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

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

ответ

11

+1 для this answer

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

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

Код клиента:

Desktop desktop = Desktop.getDesktop(); 

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

В Desktop осущ:

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). Но давайте предположим, что каждый метод выполняет другие шаги определенным образом на платформе.

Выполнение такого подхода может привести к удалению ненужных конструкций if/elseif/else, которые со временем могут привести к ошибкам (если в коде есть 6, а изменение необходимо, вы можете забыть обновить один из них, или путем копирования/вставки вы можете забыть изменить команду для выполнения)

4

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

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

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

+0

Примечание: источник Program.java находится здесь http://kickjava.com/src/org/eclipse/swt/program/Program.java.htm. Может быть, это тоже может помочь – VonC 2008-11-28 09:15:13

+0

Возможно, это очень полезно для пользователей Java 1.5 + SWT. Но использование SWT только для этого может оказаться не оптимальным. – asalamon74 2008-11-28 21:26:00

0

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

  • для Windows: «CMD/с имя_файла
  • Linux ж/гнома "гном открыть имя файла"
  • Linux ж/Kde ??
  • OSx "открытого файла"
12
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)); 
    } 
+0

Вы также можете взять с собой полиморфизм. Таким образом, вы можете добавить гибкость в реализацию. Затем вы можете избежать другой цепочки if/elseif/else для следующей операции. – OscarRyz 2008-11-28 17:37:42

+0

Вы должны использовать `xdg-open` вместо` gnome-open` или `kfmclient` или что-то еще, поэтому он лучше работает в xfce или других средах. – 2008-11-29 00:23:40

12

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

+1

Эта библиотека, похоже, решает проблему. Я не понимаю, почему люди голосовали за изобретать колесо ... – 2010-04-23 15:28:11

-3

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

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

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

5

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

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

0

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

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

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

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

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