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
How to Check If a File Is Open by Another Process (Java/Linux)
Setting/Changing the Ctime or "Change Time" Attribute on a File
Obtaining the Thread Id for Java Threads in Linux
Could Not Reserve Enough Space for Object Heap to Start Jvm
Rjava Install Error "Java_Home Cannot Be Determined from the Registry"
How to Support Both Ipv4 & Ipv6 on Java
How to Create Native Binaries for Your Java App
Connect to SQL Server from Linux via Jdbc Using Integratedsecurity (Windows Authentication)
Arval SQLexception: Fatal: Sorry, Too Many Clients Already in Postgres
Cross-Platform Way to Open a File Using Java 1.5
How to Use Chef to Update-Alternatives for Java Using Execute
Why Stringbuilder Stops Adding Elements After Using the Null Character
Eclipse Release Heap Back to System
Verify If a Process Is Running Using Its Pid in Java
Low Java Single Process Thread Limit in Red Hat Linux