使用 Java 1.5 打开文件的跨平台方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/325299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-platform way to open a file using Java 1.5
提问by asalamon74
I'm using Java 1.5 and I'd like to launch the associated application to open the file. I know that Java 1.6 introduced the Desktop API, but I need a solution for Java 1.5.
我使用的是 Java 1.5,我想启动关联的应用程序来打开文件。我知道 Java 1.6 引入了桌面 API,但我需要Java 1.5的解决方案。
So far I found a way to do it in Windows:
到目前为止,我找到了一种在 Windows 中执行此操作的方法:
Runtime.getRuntime().exec(new String[]{ "rundll32",
"url.dll,FileProtocolHandler", fileName });
Is there a cross-platform way to do it? Or at least a similar solution for Linux?
有没有跨平台的方法来做到这一点?或者至少有一个类似的Linux解决方案?
回答by Willi aus Rohr
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");
}
and
和
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));
}
回答by Dan Vinton
回答by OscarRyz
+1 for this answer
+1这个答案
Additionally I would suggest the following implementation using polymorphism:
另外,我建议使用多态实现以下实现:
This way you can add new platform easier by reducing coupling among classes.
通过这种方式,您可以通过减少类之间的耦合来更轻松地添加新平台。
The Client code:
客户端代码:
Desktop desktop = Desktop.getDesktop();
desktop.open( aFile );
desktop.imaginaryAction( aFile );
The Desktop 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>
}
}
This is only an example, in real life is not worth to create a new class only to parametrize a value ( the command string %s ) But let's do imagine that each method performs another steps in platform specific way.
这只是一个例子,在现实生活中不值得仅仅为了参数化一个值(命令字符串 %s )而创建一个新类但是让我们想象每个方法以特定于平台的方式执行另一个步骤。
Doing this kind of approach, may remove unneeded if/elseif/else constructs that with time may introduce bugs ( if there are 6 of these in the code and a change is neede, you may forget to update one of them, or by copy/pasting you may forget to change the command to execute)
执行这种方法,可能会删除不需要的 if/elseif/else 构造,这些构造随着时间的推移可能会引入错误(如果代码中有 6 个并且需要更改,您可能会忘记更新其中一个,或者通过复制/粘贴您可能忘记更改要执行的命令)
回答by Torsten Marek
Just as an addition: Rather than gnome-open, use xdg-open. It's part of the XdgUtils, which are in turn part of the LSB Desktop support package (starting with 3.2).
就像一个补充:而不是gnome-open,使用xdg-open。它是XdgUtils的一部分,而后者又是 LSB 桌面支持包(从 3.2 开始)的一部分。
You can (should) still use gnome-openas a fallback, but xdg-openwill also work on non-GNOME desktops.
您可以(应该)仍然gnome-open用作后备,但xdg-open也可以在非 GNOME 桌面上使用。
回答by boutta
SWTgives you the possibility to lokk for the standard program to open a file via:
SWT使您可以通过以下方式锁定标准程序以打开文件:
final Program p = Program.findProgram(fileExtension);
p.execute(file.getAbsolutePath());
Strictly this isn't Cross-Platform since SWT is platform dependent, but for every platform you can use a diffenrent SWT jar.
严格来说,这不是跨平台的,因为 SWT 是平台相关的,但是对于每个平台,您都可以使用不同的 SWT jar。
回答by OscarRyz
You can use the OS default way to open it for you.
您可以使用操作系统默认方式为您打开它。
- Windows: "cmd /c fileName
- Linux w/gnome "gnome-open filename"
- Linux w/Kde ??
- OSx "open filename"
- Windows:“cmd /c文件名
- Linux w/gnome "gnome-open filename"
- 带 Kde 的 Linux ??
- OSx“打开文件名”
回答by Paul Lammertsma
Another answer (by boutta) suggests using SWT. I wouldn't recommend referencing the library for this purpose only, but if you are using it already, simply execute:
另一个答案(由 boutta 提供)建议使用 SWT。我不建议仅为此目的引用库,但如果您已经在使用它,只需执行:
Program.launch("http://google.com/");
Take note that this method will only work (and return true) if a Displayobject has already been created (for instance by creating a Shell). Also take note that it must run in the main thread; e.g.:
注意,这种方法只会工作(和返回true如果)Display对象已经被(通过创建例如创建Shell)。还要注意它必须在主线程中运行;例如:
Display.syncExec(new Runnable() {
public void run() {
Program.launch("http://google.com/");
}
});
In the example above I've launched a URL, but launching files works in the same way.
在上面的示例中,我启动了一个 URL,但启动文件的工作方式相同。
回答by Dennis C
We do put the command outside somewhere in the configuration file.
我们确实将命令放在配置文件中的某个地方。
Your "JAR and source code" will be "cross-platform", but your deployment doesn't.
您的“JAR 和源代码”将是“跨平台的”,但您的部署不是。
You can also do something like this answer. You can put the classname of the factory class of the "Deskop" implementation into the setup file. (may be guide or spring, if you like)
你也可以做类似这个答案的事情。您可以将“Deskop”实现的工厂类的类名放入安装文件中。(如果您愿意,可以是指南或弹簧)

