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 の場合: ユーザーがマウスを使用して特定のディレクトリを選択すると、問題なく動作します。ユーザーがファイル名テキスト ボックスに同じディレクトリ名を入力すると、2 番目のコード スニペットは、絶対パスと標準パスが同じでないことを示します。ユーザーが末尾のバックスラッシュを入力するかどうかは問題ではありません。

これを「return」ステートメント行でデバッガーで停止し、2 つの文字列の詳細を確認すると、絶対パス文字列のハッシュ値は大きな負の数であり、正規文字列のハッシュ値は 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

Eclipe の Expressions ウィンドウにabsolute.hashCode()とを追加すると、正しい値が表示されるはずです。どちらもゼロではありません。canonical.hashCode()String にはhash0 に初期化されるメンバーがあります。その後、実行時に正しい値に更新さhashCode()れます。

したがって、文字列の計算されたハッシュabsoluteと、まだ計算されていない文字列のハッシュが表示される可能性がありcanonicalます。

ブレークポイントを入れると、Windows トリガーString.hashCode()でそれが表示されます。Windowsでの の実装は、正規化の結果をキャッシュしているようです。の間のどこかで、キャッシュされた結果マップのルックアップがトリガーされます。getCanonicalPath()absolute.hashCode()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 に答える