开发者

How can I make OS X recognize drive letters?

I know. Heresy. But I'm in a bind. I have a lot of config files that use absolute path names, which creates an incompatibility between OS X and Windows. If I can get OS X (which I'm betting is the more flexible of the two) to recognize Q:/foo/bar/bim.properties as a valid absolute fil开发者_如何学编程e name, it'll save me days of work spelunking through stack traces and config files.

In the end, I need this bit of Java test code to print "SUCCESS!" when it runs:

import java.io.*;

class DriveLetterTest {
    static public void main(String... args) {
        File f = new File("S:");
        if (f.isDirectory()) {
            System.out.println("SUCCESS!");
        } else {
            System.out.println("FAIL!");
        }
    }
}

Anyone know how this can be done?

UPDATE: Thanks for all the feedback, everyone. It's now obvious to me I really should have been clearer in my question.

Both the config files and the code that uses them belong to a third-party package I cannot change. (Well, I can change them, but that means incurring an ongoing maintenance load, which I want to avoid if at all possible.)

I'm in complete agreement with all of you who are appalled by this state of affairs. But the fact remains: I can't change the third-party code, and I really want to avoid forking the config files.


Short answer: No.
Long answer: For Java you should use System.getProperties(XXX). Then you can load a Properties file or Configuration based on what you find in os.name.
Alternate Solution just strip off the S: when you read the existing configuration files on non-Windows machines and replace them with the appropriate things.
Opinion: Personally I would bite the bullet and deal with the technical debt now, fix all the configuration files at build time when the deployment for OSX is built and be done with it.

public class WhichOS
{
    public static void main(final String[] args)
    {
        System.out.format("System.getProperty(\"os.name\") = %s\n", System.getProperty("os.name"));
        System.out.format("System.getProperty(\"os.arch\") = %s\n", System.getProperty("os.arch"));
        System.out.format("System.getProperty(\"os.version\") = %s\n", System.getProperty("os.version"));
    }
}

the output on my iMac is:

System.getProperty("os.name") = Mac OS X
System.getProperty("os.arch") = x86_64
System.getProperty("os.version") = 10.6.4


Honestly, don't hard-code absolute paths in a program, even for a single-platform app. Do the correct thing.

The following is my wrong solution, saved to remind myself not to repeat giving a misdirected advice ... shame on me.

Just create a symbolic link named Q: just at the root directory / to / itself.

$ cd /
$ ln -s / Q:
$ ln -s / S:

You might need to use sudo. Then, at the start of your program, just chdir to /.

If you don't want Q: and S: to show up in the Finder, perform

$ /Developer/Tools/SetFile -P -a V Q:
$ /Developer/Tools/SetFile -P -a V S:

which set the invisible-to-the-Finder bit of the files.


The only way you can replace java.io.File is to replace that class in rt.jar.

I don't recommend that, but the best way to do this is to grab a bsd-port of the OpenJDK code, make necessary changes, build it and redistribute the binary with your project. Write a shell script to use your own java binary and not the built-in one.

PS. Just change your config files! Practice your regex skills and save yourself a lot of time.


If you are not willing to change your config file per OS, what are they for in first place?

Every installation should have its own set of config files and use it accordingly.

But if you insist.. you just have to detect the OS version and if is not Windows, ignore the letter:

Something along the lines:

boolean isWindows = System.getProperty("os.name").toLowerCase()
        .contains("windows");

String folder = "S:";
if (isWindows && folder.matches("\\w:")) {
    folder = "/";
} else if (isWindows && folder.matches("\\w:.+")) {
    folder = folder.substring(2);// ignoring the first two letters S:
}

You get the idea


Most likely you'd have to provide a different java.io.File implementation that can parse out the file paths correctly, maybe there's one someone already made.
The real solution is to put this kind of stuff (hard-coded file paths) in configuration files and not in the source code.


Just tested something out, and discovered something interesting: In Windows, if the current directory is on the same logical volume (i.e. root is the same drive letter), you can leave off the drive letter when using a path. So you could just trim off all those drive letters and colons and you should be fine as long as you aren't using paths to items on different disks.


Here's what I finally ended up doing:

I downloaded the source code for the java.io package, and tweaked the code for java.io.File to look for path names that start with a letter and a colon. If it finds one, it prepends "/Volumes/" to the path name, coughs a warning into System.err, then continues as normal.

I've added symlinks under /Volumes to the "drives" I need mapped, so I have:

  • /Volumes/S:
  • /Volumes/Q:

I put it into its own jar, and put that jar at the front of the classpath for this project only. This way, the hack affects only me, and only this project.

Net result: java.io.File sees a path like "S:/bling.properties", and then checks the OS. If the OS is OS X, it prepends "/Volumes/", and looks for a file in /Volumes/S:/bling.properties, which is fine, because it can just follow the symlink.

Yeah, it's ugly as hell. But it gets the job done for today.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜