FileChooser在GUI选择和输入文件名之间进行区分

时间:2012-04-23 02:30:21

标签: java swing jfilechooser

我有一个使用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)调试器的怪癖。

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

2 个答案:

答案 0 :(得分:2)

仔细检查您输入的字符串完全相同

我试了一下,不假思索地键入了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 - determine symbolic links”。那里有很多答案你可能会觉得有帮助。

答案 1 :(得分:1)

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

所以你可能看到的是absolute字符串的计算哈希值,还没有canonical字符串的计算哈希值。

String.hashCode()中放置一个断点,您将在Windows上看到getCanonicalPath()触发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