Java 文件选择器GUI选择和键入文件名之间的差异

Java 文件选择器GUI选择和键入文件名之间的差异,java,swing,jfilechooser,Java,Swing,Jfilechooser,我有一个使用JFileChooser选择目录的应用程序。在这个应用程序中,我不想尝试处理符号链接,我想在多个平台上运行。因此,代码尝试确定所选文件是否为符号链接,如果是,则显示错误对话框 以下是从JFileChooser获取文件的代码 public File getDirectoryChoice(String buttonText, String currentDirectory) { File chosenFile = null; if (fileChooser == null) {

我有一个使用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;
  }
}
在Windows7上:如果用户使用鼠标选择一个给定的目录,这可以正常工作。如果用户在“文件名”文本框中键入相同的目录名,则第二个代码段指示绝对路径和规范路径不相同。用户是否输入尾随的反斜杠并不重要

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


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

请仔细检查键入的字符串是否与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;
}
我试了一下,没想到就输入了
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));

您可能还想看看这个相关的问题:“”。这里有很多答案,您可能会觉得很有帮助。

如果将
absolute.hashCode()
canonical.hashCode()
添加到Eclipe的表达式窗口中,您应该会看到正确的值-两者都不是零。字符串具有初始化为0的
哈希
成员。然后,当执行
hashCode()
时,它被更新为正确的值

因此,您可能看到的是
绝对
字符串的计算哈希和
规范
字符串的尚未计算哈希

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

因此,在
isSymbolic()
中对
return
语句设置的断点处,
absolute
有一个有效的哈希代码,
canonical
仍为零

下面是堆栈跟踪,它演示了作为
f.getCanonicalPath()
执行的
绝对.hashCode()

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
String.hashCode()行:1482[局部变量不可用]
ExpiringCache$1(HashMap).getEntry(对象)行:344
ExpiringCache$1(LinkedHashMap).get(对象)行:280
ExpiringCache.entryFor(字符串)行:83
ExpiringCache.get(字符串)行:58
WinNTFileSystem(Win32文件系统)。规范化(字符串)行:377
File.getCanonicalPath()行:559
Test.isSymbolic(文件)行:25
测试。主(字符串[])行:16
Capital C——不管你有多少经验,你仍然会被它抓住(显然)。