问题
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.
So far I found a way to do it in 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?
回答1:
+1 for this answer
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.
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)
回答2:
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));
}
回答3:
JDIC is a library that provides Desktop-like functionality in Java 1.5.
回答4:
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).
You can (should) still use gnome-open
as a fallback, but xdg-open
will also work on non-GNOME desktops.
回答5:
SWT gives you the possibility to lokk for the standard program to open a file via:
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.
回答6:
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"
回答7:
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:
Program.launch("http://google.com/");
Take note that this method will only work (and return true
) if a Display
object has already been created (for instance by creating a Shell
). Also take note that it must run in the main thread; e.g.:
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.
回答8:
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.
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)
来源:https://stackoverflow.com/questions/325299/cross-platform-way-to-open-a-file-using-java-1-5