Я использую Java 1.5 и хочу запустить соответствующее приложение, чтобы открыть файл. Я знаю, что в Java 1.6 появился Desktop API, но мне нужно решение для Java 1.5.
Пока что нашел способ сделать это в Windows:
Runtime.getRuntime().exec(new String[]{ "rundll32",
"url.dll,FileProtocolHandler", fileName });
Есть ли кроссплатформенный способ сделать это? Или хотя бы аналогичное решение для Linux?
SWT дает вам возможность заблокировать стандартную программу для открытия файла через:
final Program p = Program.findProgram(fileExtension);
p.execute(file.getAbsolutePath());
Строго говоря, это не кроссплатформенность, поскольку SWT зависит от платформы, но для каждой платформы вы можете использовать различную банку SWT.
Вероятно, это очень полезно для пользователей Java 1.5 + SWT. Но использование SWT только для этого может быть неоптимальным.
Вы можете использовать способ по умолчанию ОС, чтобы открыть его для вас.
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));
}
Вы также можете использовать полиморфизм с этим. Таким образом, вы можете добавить гибкости реализации. Тогда вы можете избежать еще одной цепочки if / elseif / else для следующей операции.
Вы должны использовать xdg-open
вместо gnome-open
или kfmclient
или чего-то еще, чтобы он лучше работал в xfce или других средах.
JDIC - это библиотека, которая обеспечивает функциональные возможности настольного компьютера в Java 1.5.
Эта библиотека, кажется, решает проблему. Я не понимаю, почему люди проголосовали за изобретение велосипеда ...
+1 за этот ответ
Кроме того, я бы предложил следующую реализацию с использованием полиморфизма:
Таким образом можно упростить добавление новой платформы за счет уменьшения связи между классами.
Клиентский код:
Desktop desktop = Desktop.getDesktop();
desktop.open( aFile );
desktop.imaginaryAction( aFile );
Рабочий стол подразумевает:
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 и требуется изменение, вы можете забыть обновить одну из них или скопировать / при вставке вы можете забыть изменить команду для выполнения)
@KrzysztofCichocki, вы не можете объяснить, почему вы думаете, что это не решение, таким образом, люди, читающие этот ответ, могут оценить, использовать его или нет.
Вы не показали никакого кода, который действительно работает и открывает браузер по умолчанию для java 1.5, просто какой-то скелет для него без какой-либо полезной реализации, поэтому это не решение.
Мы помещаем команду снаружи где-то в файле конфигурации.
Ваш «JAR и исходный код» будут «кроссплатформенными», а ваше развертывание - нет.
Вы также можете сделать что-то вроде этот ответ. Вы можете поместить имя класса фабричного класса реализации "Deskop" в установочный файл. (может быть путеводителем или пружиной, если хотите)
Просто как дополнение: вместо gnome-open
используйте xdg-open
. Это часть XdgUtils, которые, в свою очередь, являются частью пакета поддержки LSB Desktop (начиная с 3.2).
Вы можете (должны) по-прежнему использовать gnome-open
в качестве запасного варианта, но xdg-open
также будет работать на рабочих столах, отличных от GNOME.
Отличное дополнение. Я не знал об этом пакете.
Другой ответ (by boutta) предлагает использовать SWT. Я бы не рекомендовал ссылаться на библиотеку только для этой цели, но если вы ее уже используете, просто выполните:
Program.launch("http://google.com/");
Обратите внимание, что этот метод будет работать (и вернуть true
), если объект Display
уже был создан (например, путем создания Shell
). Также обратите внимание, что он должен выполняться в основном потоке; например.:
Display.syncExec(new Runnable() {
public void run() {
Program.launch("http://google.com/");
}
});
В приведенном выше примере я запустил URL-адрес, но запуск файлов работает точно так же.
Примечание: источник Program.java находится здесь kickjava.com/src/org/eclipse/swt/program/Program.java.htm. Может быть, это тоже может помочь