4

我有一个使用 JFileChooser 选择目录的应用程序。在这个应用程序中,我不想尝试处理符号链接,我想在多个平台上运行。因此,代码尝试确定所选文件是否为符号链接,如果是,则显示错误对话框。

这是从 JFileChooser 获取文件的代码。

public File getDirectoryChoice(String buttonText, String currentDirectory)
{
  File chosenFile = null;
  if (fileChooser == null) { fileChooser = new JFileChooser(); }
  if (currentDirectory != null) 
    { fileChooser.setCurrentDirectory(new File(currentDirectory)); }
  fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  fileChooser.setApproveButtonText(buttonText);
  int returnValue = fileChooser.showOpenDialog(mainFrame);
  if (returnValue == JFileChooser.APPROVE_OPTION)
  {
    chosenFile = fileChooser.getSelectedFile();
  }
  return chosenFile;
}

这是我用来确定所选文件是否为符号链接的代码:

public static boolean isSymbolic(File f)
{
  try
  { 
    String absolute = f.getAbsolutePath();
    String canonical = f.getCanonicalPath();
    return !(absolute.equals(canonical));
  }
  catch (IOException ioe)
  {
    return false;
  }
}

在 Windows 7 上:如果用户使用鼠标选择一个给定的目录,这可以正常工作。如果用户在文件名文本框中键入相同的目录名,则第二个代码片段表明绝对路径和规范路径不同。用户是否输入尾部反斜杠并不重要。

当我在'return'语句行的调试器中停止这个并查看两个字符串的详细信息时,绝对路径字符串的哈希值是一个很大的负数,而规范字符串的哈希值为0。我不知道为什么会这样,实际上想知道这是否是(eclipse)调试器的怪癖。

谁能告诉我为什么会有这种差异?

4

2 回答 2

2

仔细检查您输入的字符串是否与 JFileChooser 返回的字符串完全相同。

我试过了,没想到我打字了c:\temp。就像在您的测试中一样,isSymbolic()方法返回true. 然而,经过仔细检查,我注意到当我在文件选择器中选择此路径时,它C:\temp反而返回(注意大写C)。

所以即使它很丑,你也可以添加一个像这样的特殊情况:

    if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
        return !(absolute.equalsIgnoreCase(canonical));
    else
        return !(absolute.equals(canonical));

您可能还想查看这个相关问题:“ Java 1.6 - 确定符号链接”。那里有很多答案,您可能会觉得有帮助。

于 2012-04-23T03:03:35.957 回答
1

如果您在 Ecipe 的“表达式”窗口中添加absolute.hashCode()和,您应该会看到正确的值 - 两者都不为零。canonical.hashCode()字符串的hash成员初始化为 0。然后在hashCode()执行时更新为正确的值。

所以你可能看到的是字符串的计算哈希值,absolute而不是字符串的计算哈希值canonical

放一个断点String.hashCode(),你会getCanonicalPath()在 Windows 触发器上看到它absolute.hashCode()。Windows上的实现似乎getCanonicalPath()缓存了规范化的结果。介于两者之间的某个地方,WinNTFileSystem.canonicalize()缓存结果映射中的查找会触发absolute.hashCode()

所以在你在return语句中设置的断点处isSymbolic()absolute有一个有效的哈希码并且canonical它仍然为零。

这是演示absolute.hashCode()执行结果的堆栈跟踪f.getCanonicalPath()

String.hashCode() line: 1482 [local variables unavailable]  
ExpiringCache$1(HashMap<K,V>).getEntry(Object) line: 344    
ExpiringCache$1(LinkedHashMap<K,V>).get(Object) line: 280   
ExpiringCache.entryFor(String) line: 83 
ExpiringCache.get(String) line: 58  
WinNTFileSystem(Win32FileSystem).canonicalize(String) line: 377 
File.getCanonicalPath() line: 559   
Test.isSymbolic(File) line: 25  
Test.main(String[]) line: 16
于 2012-04-23T03:53:26.083 回答