Cross-Platform Way to Open a File Using Java 1.5

Cross-platform way to open a file using Java 1.5

+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)

cross platform way to explore the containing folder of a file

What happens if you call getDesktop().open(file.getParentFile()) ?

Open a file with an external application on Java

With JDK1.6, the java.awt.Desktop class can be useful.

public static void open(File document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.open(document);
}

Import Data into a Java program on different platforms?

Resources in J2SE, Android and (probably) J2ME that are 'embedded application resources' can (and thereby should) be accessed via. URL.

Obtain the URL using something like:

URL periodicTableData = this.getClass().getResource(
"/relative/path/to/periodicTable.dat");

I assume there are different installation methods for different platforms?

'Static' resources, ones that don't change, can be added to a Jar. If that Jar is on the run-time class-path of the app., they will be found using getResource().

The data .. (is).. a list of all elements of the periodic table (in both symbol and full name) verse their atomic mass, up to about 7 decimal places each.

As mentioned by gt_ebuddy, a CSV might be used for this. OTOH I would tend to use XML. XML can handle more complicated structures than immediately needed here, but does offer the advantage of good inbuilt support (on J2SE at least), and (encoded in UTF-8) will be readable across platforms.

How to allow running only one instance of a Java program at a time?

I think your suggestion of opening a port to listen when you start your application is the best idea.

It's very easy to do and you don't need to worry about cleaning it up when you close your application. For example, if you write to a file but someone then kills the processes using Task Manager the file won't get deleted.

Also, if I remember correctly there is no easy way of getting the PID of a Java process from inside the JVM so don't try and formulate a solution using PIDs.

Something like this should do the trick:

private static final int PORT = 9999;
private static ServerSocket socket;

private static void checkIfRunning() {
try {
//Bind to localhost adapter with a zero connection queue
socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
}
catch (BindException e) {
System.err.println("Already running.");
System.exit(1);
}
catch (IOException e) {
System.err.println("Unexpected error.");
e.printStackTrace();
System.exit(2);
}
}

This sample code explicitly binds to 127.0.0.1 which should avoid any firewall warnings, as any traffic on this address must be from the local system.

When picking a port try to avoid one mentioned in the list of Well Known Ports. You should ideally make the port used configurable in a file or via a command line switch in case of conflicts.

Downgrading an application from Java 1.6 to Java 1.5

I suggest you look in the manifest for each library for lines like

Bundle-RequiredExecutionEnvironment: J2SE-1.3
X-Compile-Target-JDK: 1.5
Build-Jdk: 1.5.0_22
Created-By: 1.6.0_21-b07 (Sun Microsystems Inc.)

I would only take the create by if no other option appears.

The only way to know for sure is to example a class in the library (assuming all classes where built for the same version)

javap -v -classpath net\sf\trove4j\trove4j\3.0.2\trove4j-3.0.2.jar gnu/trove/list/TLongList | grep version

minor version: 0
major version: 49

A table of versions are

major  minor Java platform version 
45 3 1.0
45 3 1.1
46 0 1.2
47 0 1.3
48 0 1.4
49 0 1.5
50 0 1.6
51 0 1.7
52 0 1.8

For more details http://en.wikipedia.org/wiki/Java_class_file

How do I get the file extension of a file in Java?

In this case, use FilenameUtils.getExtension from Apache Commons IO

Here is an example of how to use it (you may specify either full path or just file name):

import org.apache.commons.io.FilenameUtils;

// ...

String ext1 = FilenameUtils.getExtension("/path/to/file/foo.txt"); // returns "txt"
String ext2 = FilenameUtils.getExtension("bar.exe"); // returns "exe"

Maven dependency:

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

Gradle Groovy DSL

implementation 'commons-io:commons-io:2.6'

Gradle Kotlin DSL

implementation("commons-io:commons-io:2.6")

Others https://search.maven.org/artifact/commons-io/commons-io/2.6/jar



Related Topics



Leave a reply



Submit