如何让OS X识别驱动器盘符?

3

我知道这是异端邪说,但我陷入了困境。我有很多使用绝对路径名的配置文件,这在OS X和Windows之间创建了不兼容性。如果我可以让OS X(我打赌它是两者中更灵活的)将 Q:/foo/bar/bim.properties 识别为有效的绝对文件名,那么它将为我节省数天的工作时间,避免我浏览堆栈跟踪和配置文件。

最终,当此Java测试代码运行时,我需要它输出“SUCCESS!”:

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!");
        }
    }
}

有人知道如何实现这个吗?

更新:感谢大家的反馈,现在对我来说很明显,我应该在问题上更清楚。

配置文件和使用它们的代码都属于一个第三方包,我无法更改。(好吧,我可以更改它们,但这意味着要承担持续的维护负担,如果可能的话,我想避免。)

我完全同意所有对此情况感到震惊的人。但事实仍然存在:我不能更改第三方代码,而且我真的想避免分叉配置文件。


我猜这个可能做不到,但这是一个有趣的问题。 - A. Levy
1
我的问题是,在Mac系统上Q会被翻译成什么?你能区分应用程序是否在Windows或Mac上运行,并在那时进行翻译吗? - Fosco
我想将Q:映射到类似~/workspace的东西。不幸的是,“Q:/…”的引用散布在数十个配置文件中,并且被我无法控制的代码使用。因此,在OS X上使用文件路径的唯一方法是强制向JVM提供替代的java.io.File实现。 - DeathB4Decaf
不是这样的,请看我在运行时提供的另一种解决方案。 - user177800
重复:http://stackoverflow.com/questions/3258762/how-can-i-make-os-x-recognize-drive-letters - brainimus
2
回应您对多个答案的评论:当然,这个第三方包有配置文件允许您更改它们,因此实际上为OSX更改它们并不是分离该包。最坏的情况下,您可以将其作为您的OSX安装的一部分,在安装时执行find xxx | sed xxx以修改“未分叉”的文件。 - Stephen P
7个回答

3
说实话,在编程中不要硬编码绝对路径,即使是单平台应用程序也不要这样做。要做正确的事情。
以下是我错误的解决方案,保存下来提醒自己不要重复给出错误的建议...我真惭愧。
只需在根目录/创建一个名为Q:符号链接指向/本身。
$ cd /
$ ln -s / Q:
$ ln -s / S:

你可能需要使用sudo。然后,在程序开始时,只需chdir/
如果你不想让Finder中出现Q:S:,请执行
$ /Developer/Tools/SetFile -P -a V Q:
$ /Developer/Tools/SetFile -P -a V S:

这会设置文件的“对Finder不可见”位。


如果我安装了一些像这样在我的文件系统中散布符号链接的软件,我会感到很恼火! - user177800
我知道,我知道... :p 但是我只是为OP提供了最简单的解决方案!好吧,我还添加了额外的指令来隐藏文件不让Finder看到 :p - Yuji
错误的建议比没有建议还糟糕,这并不简单,它是一种最糟糕的反模式黑客方式,你甚至提出这样的建议真是可耻。 - user177800
如果 OP 不能针对不同的操作系统使用不同的配置文件,我认为创建符号链接会更加困难。 - OscarRyz

3

简短回答: 不可以。
详细回答: 对于Java,您应该使用System.getProperties(XXX)。然后,您可以根据在os.name中找到的内容加载Properties文件或Configuration。
替代方案: 在非Windows机器上读取现有配置文件时,只需去掉S:,并将其替换为适当的内容即可。
个人观点: 我个人认为,现在应该处理技术债务,解决所有构建时间和OSX部署时的配置文件问题,并结束它。

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"));
    }
}

我的iMac的输出是:

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

我认为在这种情况下,“长答案”就是“明智的答案”——为不同的操作系统使用不同的配置。 - matt b
我完全同意你所说的一切。我的代码没有硬编码文件名,不关心它运行在哪个操作系统上,也不关心它在文件系统中的位置等等。然而,解析路径的代码是第三方代码,我无法修改。而且配置文件必须在OS X和Windows上都能工作。所以我唯一剩下的选择就是调整OS X来有效地将驱动器字母符号链接到目录,或者调整java.io.File实现。 - DeathB4Decaf

2

如果你不愿意根据操作系统更改配置文件,那么它们的作用是什么呢?

每个安装都应该有自己的一套配置文件,并相应地使用它。

但是如果你坚持这样做...你只需要检测操作系统版本,如果不是Windows,则忽略字母:

大致如下:

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:
}

你明白了吗?

2
刚刚测试了一些东西,发现了一些有趣的事情:在Windows中,如果当前目录位于同一逻辑卷上(即根目录是相同的驱动器字母),则在使用路径时可以省略驱动器字母。因此,只要您不使用指向不同磁盘上项目的路径,就可以裁剪掉所有那些驱动器字母和冒号,这样就可以正常工作了。

好的方法...在多个驱动器上配置系统有时是不可避免的,但即使如此,也可以使用符号链接将结果统一为一个单一的文件系统树。我认为,需要驱动器字母路径是一种反模式。 - philwalk

2

你唯一可以替换java.io.File的方法是在rt.jar中替换该类。

我不建议这样做,但最好的方法是获取OpenJDK代码的BSD端口,进行必要的更改,构建它并重新分发二进制文件与您的项目。编写一个shell脚本来使用您自己的java二进制文件而不是内置的二进制文件。

PS. 只需更改配置文件!练习你的正则表达式技能,节省大量时间。


1

很可能你需要提供一个不同的java.io.File实现,可以正确解析文件路径,也许已经有人做过了。
真正的解决方案是将这种东西(硬编码的文件路径)放在配置文件中,而不是源代码中。


唉,硬编码路径已经在配置文件中了。有很多这样的文件。而且这些相同的配置文件必须在OS X和Windows上使用。所以我要么编写一个脚本,在所有这些路径上进行查找和替换,调整OS X以识别驱动器号并让我将它们映射到任意目录,或者(正如你建议的那样)为JVM本身提供一个替代的java.io.File实现。 - DeathB4Decaf
我同意。你的应用程序中应该有这样的固定编码路径。通过使用相对路径、使用明确定义的目录或将路径放入配置文件中来避免它们。 - Gamlor
1
你愿意提供一个新的文件实现方式,但不更改你的文本配置文件吗?:-/ - OscarRyz
1
我认为你应该更改你的配置文件。 - gtrak
配置文件是我无法控制的第三方包的一部分。我可以修改它们,但这意味着基本上要分叉该软件包,并承担保持我的配置与主干线同步的维护负担。在这种情况下,我愿意考虑调整java.io.File,因为它几乎不会产生持续的维护负担。这是一个hack,但只影响我,而且只有在升级JVM时才会受到影响。尝试修改解析代码或配置文件意味着每当团队中的其他人添加新的配置属性/更改时都会出现日常头痛。 - DeathB4Decaf
不要提供替代的文件实现,如果您可以访问源代码,只需创建一个包装对象来进行翻译,并将其放置在“File”位置即可。 - gtrak

1

这是我最终采取的做法:

我下载了java.io包的源代码,并调整了java.io.File的代码,以查找以字母和冒号开头的路径名。如果找到一个,它会在路径名前面添加“/Volumes/”,并向System.err发出警告,然后像往常一样继续执行。

我在/Volumes下添加了符号链接,将需要映射的“驱动器”映射到:

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

我将其放入自己的jar文件中,并将该jar文件放在仅此项目的类路径的最前面。这样,这个hack只影响我,而且只影响这个项目。

最终结果:java.io.File看到像“S:/bling.properties”这样的路径,然后检查操作系统。如果操作系统是OS X,则在路径前面添加“/Volumes/”,并在/Volumes/S:/bling.properties中查找文件,这是可以的,因为它只需跟随符号链接即可。

是的,这很丑陋。但它今天完成了工作。


哈哈,不用谢 :-)。很高兴听到它起作用了,我从来没有做过这样的事情! - gtrak
啊,我应该在这里发布一个附录。由于OS X一直在清理/Volumes下的符号链接,所以我不得不将它们放在~/Drives/下。 - DeathB4Decaf
如果避免使用全局符号链接并使用用户目录,可能会稍微好一些。就像你说你想要“〜/工作区”一样。 - gtrak
Gary,你说得很对。请看我的补充说明,我把它们放在了~/Drives下面。 - DeathB4Decaf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接